neoload 1.3.14.dev3__tar.gz → 1.3.17__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. {neoload-1.3.14.dev3 → neoload-1.3.17}/.github/workflows/python-integration-tests.yml +2 -2
  2. {neoload-1.3.14.dev3 → neoload-1.3.17}/.github/workflows/python-package.yml +6 -6
  3. {neoload-1.3.14.dev3 → neoload-1.3.17}/.github/workflows/python-post-release-changelog-pr.yml +4 -4
  4. {neoload-1.3.14.dev3 → neoload-1.3.17}/.github/workflows/python-release.yml +3 -3
  5. {neoload-1.3.14.dev3 → neoload-1.3.17}/.gitignore +3 -0
  6. {neoload-1.3.14.dev3 → neoload-1.3.17}/PKG-INFO +19 -3
  7. {neoload-1.3.14.dev3 → neoload-1.3.17}/README.md +9 -1
  8. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/docker/Dockerfile +1 -1
  9. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/azure_devops/neoload-cli-docker.yml +1 -1
  10. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/azure_devops/neoload-cli-dyninfra.yml +1 -1
  11. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/github/neoload-github-actions-demo.yml +1 -1
  12. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/__main__.py +1 -1
  13. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/project.py +35 -5
  14. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/report.py +1 -1
  15. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/neoLoad_project.py +5 -3
  16. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/rest_crud.py +2 -1
  17. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/tools.py +1 -1
  18. neoload-1.3.17/neoload/version.py +1 -0
  19. neoload-1.3.17/neoload/version_manager.py +4 -0
  20. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload.egg-info/PKG-INFO +19 -3
  21. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload.egg-info/SOURCES.txt +3 -0
  22. neoload-1.3.17/requirements.txt +3 -0
  23. {neoload-1.3.14.dev3 → neoload-1.3.17}/setup.py +1 -1
  24. neoload-1.3.17/tests/commands/project/test_upload_with_password.py +49 -0
  25. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/helpers/test_utils.py +1 -0
  26. neoload-1.3.17/tests/neoload_projects/example_2.zip +0 -0
  27. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/report/expected_custom_report.html +2 -8
  28. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/report/expected_custom_report_filtered.html +2 -8
  29. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/report/expected_template_trends.html +2 -8
  30. neoload-1.3.14.dev3/neoload/version.py +0 -1
  31. neoload-1.3.14.dev3/requirements.txt +0 -2
  32. {neoload-1.3.14.dev3 → neoload-1.3.17}/.travis.yml +0 -0
  33. {neoload-1.3.14.dev3 → neoload-1.3.17}/CHANGELOG.md +0 -0
  34. {neoload-1.3.14.dev3 → neoload-1.3.17}/LICENSE +0 -0
  35. {neoload-1.3.14.dev3 → neoload-1.3.17}/MANIFEST.in +0 -0
  36. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/aws/.nlignore +0 -0
  37. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/aws/buildspec.yaml +0 -0
  38. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/azure_devops/.nlignore +0 -0
  39. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/azure_devops/Azure_DevOps_Pipeline_NeoLoad_CLI.jpg +0 -0
  40. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/azure_devops/Azure_DevOps_Pipeline_NeoLoad_SLA_jUnit.jpg +0 -0
  41. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/azure_devops/README.md +0 -0
  42. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/bamboo-specs/.nlignore +0 -0
  43. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/bamboo-specs/Bamboo_Pipeline_NeoLoad_SLA_jUnit.jpg +0 -0
  44. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/bamboo-specs/README.md +0 -0
  45. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/bamboo-specs/bamboo-v1.yaml +0 -0
  46. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/bamboo-specs/bamboo-v2.yaml +0 -0
  47. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/gitlab/.nlignore +0 -0
  48. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/gitlab/openshift.gitlab-ci.yml +0 -0
  49. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/jenkins/Jenkinsfile_dyninfra +0 -0
  50. {neoload-1.3.14.dev3 → neoload-1.3.17}/examples/pipelines/jenkins/Jenkinsfile_slafails +0 -0
  51. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/__init__.py +0 -0
  52. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/__init__.py +0 -0
  53. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/config.py +0 -0
  54. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/docker.py +0 -0
  55. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/fastfail.py +0 -0
  56. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/login.py +0 -0
  57. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/logout.py +0 -0
  58. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/logs.py +0 -0
  59. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/logs_url.py +0 -0
  60. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/run.py +0 -0
  61. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/status.py +0 -0
  62. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/stop.py +0 -0
  63. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/test_results.py +0 -0
  64. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/test_settings.py +0 -0
  65. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/validate.py +0 -0
  66. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/wait.py +0 -0
  67. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/workspaces.py +0 -0
  68. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/commands/zones.py +0 -0
  69. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/__init__.py +0 -0
  70. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/bad_as_code_exception.py +0 -0
  71. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/cli_exception.py +0 -0
  72. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/config_global.py +0 -0
  73. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/displayer.py +0 -0
  74. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/docker_lib.py +0 -0
  75. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/filtering.py +0 -0
  76. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/hooks.py +0 -0
  77. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/logs_tools.py +0 -0
  78. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/logs_traduction_map.py +0 -0
  79. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/name_resolver.py +0 -0
  80. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/paths.py +0 -0
  81. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/running_tools.py +0 -0
  82. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/schema_validation.py +0 -0
  83. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/neoload_cli_lib/user_data.py +0 -0
  84. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/__init__.py +0 -0
  85. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/__init__.py +0 -0
  86. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/builtin_console_summary.j2 +0 -0
  87. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/builtin_transactions_csv.j2 +0 -0
  88. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/common/common.js +0 -0
  89. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/common/external_data.html.j2 +0 -0
  90. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/common/general_details.html.j2 +0 -0
  91. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/common/header.j2 +0 -0
  92. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/common/hits_per_second.html.j2 +0 -0
  93. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/common/running_vus.html.j2 +0 -0
  94. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/common/styles.css +0 -0
  95. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/common/transactions.html.j2 +0 -0
  96. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/common/workload_characteristics.html.j2 +0 -0
  97. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/custom_transactions_export.j2 +0 -0
  98. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/sample-custom-report.html.j2 +0 -0
  99. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/sample-trends-report.html.j2 +0 -0
  100. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/trends/general_details.html.j2 +0 -0
  101. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/trends/transaction_trends.html.j2 +0 -0
  102. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload/resources/jinja/trends/trends.js +0 -0
  103. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload.egg-info/dependency_links.txt +0 -0
  104. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload.egg-info/entry_points.txt +0 -0
  105. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload.egg-info/requires.txt +0 -0
  106. {neoload-1.3.14.dev3 → neoload-1.3.17}/neoload.egg-info/top_level.txt +0 -0
  107. {neoload-1.3.14.dev3 → neoload-1.3.17}/notes/PSB_20200421_TODO.txt +0 -0
  108. {neoload-1.3.14.dev3 → neoload-1.3.17}/notes/acceptance.txt +0 -0
  109. {neoload-1.3.14.dev3 → neoload-1.3.17}/pull_request_template.md +0 -0
  110. {neoload-1.3.14.dev3 → neoload-1.3.17}/pytest.ini +0 -0
  111. {neoload-1.3.14.dev3 → neoload-1.3.17}/resources/as-code.latest.schema.json +0 -0
  112. {neoload-1.3.14.dev3 → neoload-1.3.17}/setup.cfg +0 -0
  113. {neoload-1.3.14.dev3 → neoload-1.3.17}/sonar-project.properties +0 -0
  114. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/__init__.py +0 -0
  115. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/docker/test_docker_cleanups.py +0 -0
  116. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/docker/test_docker_connections.py +0 -0
  117. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/docker/test_docker_hooks.py +0 -0
  118. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/fastfail/test_fastfail_slas.py +0 -0
  119. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/project/test_upload.py +0 -0
  120. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/report/test_report.py +0 -0
  121. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/report/test_report_json_output.py +0 -0
  122. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/report/test_report_templates.py +0 -0
  123. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/report/test_report_transactions.py +0 -0
  124. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/report/test_report_trends.py +0 -0
  125. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/report/test_trends_json_output.py +0 -0
  126. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/report/test_trends_templates.py +0 -0
  127. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/status/test_status_with_names.py +0 -0
  128. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_config.py +0 -0
  129. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_login.py +0 -0
  130. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_logout.py +0 -0
  131. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_logs/test_logs.py +0 -0
  132. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_logs_url.py +0 -0
  133. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_results/test_result_delete.py +0 -0
  134. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_results/test_result_ls.py +0 -0
  135. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_results/test_result_patch.py +0 -0
  136. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_results/test_result_put.py +0 -0
  137. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_run.py +0 -0
  138. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_settings/test_create.py +0 -0
  139. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_settings/test_createorpatch.py +0 -0
  140. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_settings/test_delete.py +0 -0
  141. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_settings/test_ls.py +0 -0
  142. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_settings/test_patch.py +0 -0
  143. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_settings/test_put.py +0 -0
  144. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/test_validate.py +0 -0
  145. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/wait/test_wait.py +0 -0
  146. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/workspaces/test_workspace_ls.py +0 -0
  147. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/workspaces/test_workspace_use.py +0 -0
  148. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/commands/zones/test_zones.py +0 -0
  149. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/conftest.py +0 -0
  150. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/helpers/__init__.py +0 -0
  151. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/expected/fastfail.log +0 -0
  152. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/expected/junit-sla.xml +0 -0
  153. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/expected/run.log +0 -0
  154. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/expected/summary.txt +0 -0
  155. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/runAllScripts.sh +0 -0
  156. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/cleanup.sh +0 -0
  157. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/project.upload.test.sh +0 -0
  158. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/results.delete.test.sh +0 -0
  159. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/results.patch.test.sh +0 -0
  160. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/results.put.test.sh +0 -0
  161. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/run.fastfail.test.sh +0 -0
  162. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/run.oneliner.test.sh +0 -0
  163. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/run.test.sh +0 -0
  164. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/settings.create.delete.test.sh +0 -0
  165. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/settings.patch.test.sh +0 -0
  166. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/settings.put.test.sh +0 -0
  167. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/validate.test.sh +0 -0
  168. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/wait.test.sh +0 -0
  169. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/integration/scripts/zones.ls.test.sh +0 -0
  170. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_cli_lib/test_SchemaValidation.py +0 -0
  171. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_cli_lib/test_displayer.py +0 -0
  172. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_cli_lib/test_docker.py +0 -0
  173. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_cli_lib/test_filtering.py +0 -0
  174. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_cli_lib/test_rest_crud.py +0 -0
  175. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_cli_lib/test_running_tools.py +0 -0
  176. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_cli_lib/test_tools.py +0 -0
  177. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_cli_lib/test_user_data.py +0 -0
  178. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/.nlignore +0 -0
  179. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/broken_yaml.yaml +0 -0
  180. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/empty.yaml +0 -0
  181. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/example_1/.gitlab-ci.yml +0 -0
  182. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/example_1/.nlignore +0 -0
  183. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/example_1/data/cities.csv +0 -0
  184. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/example_1/default.yaml +0 -0
  185. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/example_1/paths/geosearch_get.yaml +0 -0
  186. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/example_1/slas/prod.yaml +0 -0
  187. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/example_1/slas/uat.yaml +0 -0
  188. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/example_1.zip +0 -0
  189. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/invalid_to_schema.yaml +0 -0
  190. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/neoload_projects/simpledemo.yml +0 -0
  191. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/__init__.py +0 -0
  192. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/expected_neoload_junit_slas.xml +0 -0
  193. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/expected_summary_text_no_sla.txt +0 -0
  194. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/expected_summary_text_with_sla.txt +0 -0
  195. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/jinja/__init__.py +0 -0
  196. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/report/expected_custom_transactions.csv +0 -0
  197. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/report/expected_report.json +0 -0
  198. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/report/expected_report_filtered.json +0 -0
  199. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/report/expected_template_transactions.json +0 -0
  200. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/report/expected_template_transactions_csv.csv +0 -0
  201. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/report/expected_trends.json +0 -0
  202. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/report/raw_expected_custom_report.html +0 -0
  203. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/resources/report/raw_expected_report.json +0 -0
  204. {neoload-1.3.14.dev3 → neoload-1.3.17}/tests/test_readme.py +0 -0
@@ -14,11 +14,11 @@ jobs:
14
14
  runs-on: ubuntu-latest
15
15
 
16
16
  steps:
17
- - uses: actions/checkout@v2
17
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
18
18
  with:
19
19
  fetch-depth: 0
20
20
  - name: Set up Python 3.x
21
- uses: actions/setup-python@v2
21
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
22
22
  with:
23
23
  python-version: '3.x'
24
24
  - name: Install dependencies
@@ -19,7 +19,7 @@ jobs:
19
19
  runs-on: ubuntu-latest
20
20
  steps:
21
21
  - name: Checkout code
22
- uses: actions/checkout@v2
22
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
23
23
  with:
24
24
  fetch-depth: 2
25
25
 
@@ -64,9 +64,9 @@ jobs:
64
64
  echo "merge_to_trunk: ${{ env.merge_to_trunk }}"
65
65
  echo "integration_moment: ${{ env.integration_moment }}"
66
66
  echo "docker_files_changed: ${{ env.docker_files_changed }}"
67
- - uses: actions/checkout@v2
67
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
68
68
  - name: Set up Python ${{ matrix.python-version }}
69
- uses: actions/setup-python@v2
69
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
70
70
  with:
71
71
  python-version: ${{ matrix.python-version }}
72
72
  - name: "If-FullTesting: Pre-cache Images"
@@ -76,7 +76,7 @@ jobs:
76
76
  docker pull ${{ env.image_lg }}
77
77
  - name: Install dependencies
78
78
  run: |
79
- python -m pip install --upgrade pip
79
+ python -m pip install --upgrade pip setuptools wheel
80
80
  python -m pip install .
81
81
  python -m pip install coverage
82
82
  if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
@@ -95,7 +95,7 @@ jobs:
95
95
  coverage3 combine
96
96
  coverage3 xml
97
97
  - name: SonarCloud Scan
98
- uses: sonarsource/sonarcloud-github-action@master
98
+ uses: SonarSource/sonarqube-scan-action@v6.0.0
99
99
  env:
100
100
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
101
101
  SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
@@ -103,7 +103,7 @@ jobs:
103
103
  if: failure()
104
104
  run: zip -r tests.zip tests/
105
105
  - name: Upload Test Folder on failure
106
- uses: actions/upload-artifact@v2
106
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
107
107
  if: failure()
108
108
  with:
109
109
  name: test-folder ${{ matrix.node-version }}
@@ -14,7 +14,7 @@ jobs:
14
14
  new_branch_name: CHANGELOG-${{ github.event.inputs.tag }}
15
15
  #if: ${{ !contains(github.ref, 'rc') && !contains(github.ref, 'dev') }}
16
16
  steps:
17
- - uses: actions/checkout@v3
17
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
18
18
  with:
19
19
  token: ${{ secrets.GITHUB_TOKEN }}
20
20
  ref: refs/heads/master
@@ -30,7 +30,7 @@ jobs:
30
30
  git branch
31
31
  git status
32
32
 
33
- - uses: ruby/setup-ruby@v1
33
+ - uses: ruby/setup-ruby@bb6434c747fa7022e12fa1cae2a0951fcffcff26 # v1.253.0
34
34
  with:
35
35
  ruby-version: 3.2
36
36
  - name: Update Changelog for Dist
@@ -51,7 +51,7 @@ jobs:
51
51
  git log -n 5
52
52
  git push --set-upstream origin ${{ env.new_branch_name }}
53
53
  - name: pull-request
54
- uses: repo-sync/pull-request@v2
54
+ uses: repo-sync/pull-request@7e79a9f5dc3ad0ce53138f01df2fad14a04831c5 # v2.12.1
55
55
  with:
56
56
  source_branch: "${{ env.new_branch_name }}"
57
57
  destination_branch: "master"
@@ -60,7 +60,7 @@ jobs:
60
60
  pr_draft: true
61
61
  github_token: ${{ secrets.GITHUB_TOKEN }}
62
62
  - name: Archive Changelog
63
- uses: actions/upload-artifact@v3
63
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
64
64
  if: always()
65
65
  with:
66
66
  name: CHANGELOG
@@ -9,9 +9,9 @@ jobs:
9
9
  if: ${{ github.event.base_ref == 'refs/heads/master' || contains(github.ref, '.dev') }}
10
10
  runs-on: ubuntu-latest
11
11
  steps:
12
- - uses: actions/checkout@v2
12
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
13
13
  - name: Set up Python 3.x
14
- uses: actions/setup-python@v2
14
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
15
15
  with:
16
16
  python-version: '3.x'
17
17
  - name: Prepare distribution
@@ -25,6 +25,6 @@ jobs:
25
25
  python setup.py sdist bdist_wheel
26
26
  - name: Publish distribution to PyPI
27
27
  if: startsWith(github.ref, 'refs/tags')
28
- uses: pypa/gh-action-pypi-publish@release/v1
28
+ uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
29
29
  with:
30
30
  password: ${{ secrets.PYPI_TOKEN }}
@@ -10,3 +10,6 @@ coverage.xml
10
10
  htmlcov/
11
11
  build/
12
12
  dist/
13
+ neoload/version.py
14
+ venv/
15
+ .venv/
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: neoload
3
- Version: 1.3.14.dev3
3
+ Version: 1.3.17
4
4
  Summary: A command-line native utility for launching and observing NeoLoad performance tests
5
5
  Home-page: https://github.com/Neotys-Labs/neoload-cli
6
6
  Author: Neotys
@@ -28,8 +28,16 @@ Requires-Dist: pyparsing
28
28
  Requires-Dist: simplejson
29
29
  Requires-Dist: colorama
30
30
  Requires-Dist: importlib-resources
31
+ Dynamic: author
32
+ Dynamic: description
33
+ Dynamic: description-content-type
34
+ Dynamic: home-page
35
+ Dynamic: license
36
+ Dynamic: license-file
37
+ Dynamic: requires-dist
38
+ Dynamic: summary
31
39
 
32
- # NeoLoad CLI [![Build Status](https://github.com/Neotys-Labs/neoload-cli/workflows/Python%20package/badge.svg?branch=master)](https://github.com/Neotys-Labs/neoload-cli/actions?query=workflow%3A%22Python+package%22+branch%3A%22master%22)
40
+ # NeoLoad CLI [![Python package](https://github.com/Neotys-Labs/neoload-cli/actions/workflows/python-package.yml/badge.svg?branch=master)](https://github.com/Neotys-Labs/neoload-cli/actions/workflows/python-package.yml)
33
41
 
34
42
  ## Overview
35
43
 
@@ -469,6 +477,14 @@ neoload wait cur
469
477
 
470
478
  [An example for Jenkins pipeline is found here.](examples/pipelines/jenkins/Jenkinsfile_slafails)
471
479
 
480
+ ## Troubleshooting
481
+ ### Windows and non UTF-8 characters
482
+ Windows use default encoding as ASCII, but the NeoLoad CLI needs UTF-8 encoding.\
483
+ Before running some commands like `neoload report` on windows, you need to set environment variable `set PYTHONUTF8=1`\
484
+ More info [here](https://docs.python.org/3/using/windows.html#utf-8-mode) and [here](https://docs.python.org/3/library/os.html#utf8-mode).
485
+ Note that with Python 3.15, no need to do that anymore [PEP 686 – Make UTF-8 mode default](https://peps.python.org/pep-0686/)
486
+
487
+
472
488
  ## Packaging the CLI with Build Agents
473
489
  Many of the above CI examples include a step to explicitly install the NeoLoad CLI as part of the
474
490
  build steps. However, if you want the CLI baked into some build agent directly so that it
@@ -1,4 +1,4 @@
1
- # NeoLoad CLI [![Build Status](https://github.com/Neotys-Labs/neoload-cli/workflows/Python%20package/badge.svg?branch=master)](https://github.com/Neotys-Labs/neoload-cli/actions?query=workflow%3A%22Python+package%22+branch%3A%22master%22)
1
+ # NeoLoad CLI [![Python package](https://github.com/Neotys-Labs/neoload-cli/actions/workflows/python-package.yml/badge.svg?branch=master)](https://github.com/Neotys-Labs/neoload-cli/actions/workflows/python-package.yml)
2
2
 
3
3
  ## Overview
4
4
 
@@ -438,6 +438,14 @@ neoload wait cur
438
438
 
439
439
  [An example for Jenkins pipeline is found here.](examples/pipelines/jenkins/Jenkinsfile_slafails)
440
440
 
441
+ ## Troubleshooting
442
+ ### Windows and non UTF-8 characters
443
+ Windows use default encoding as ASCII, but the NeoLoad CLI needs UTF-8 encoding.\
444
+ Before running some commands like `neoload report` on windows, you need to set environment variable `set PYTHONUTF8=1`\
445
+ More info [here](https://docs.python.org/3/using/windows.html#utf-8-mode) and [here](https://docs.python.org/3/library/os.html#utf8-mode).
446
+ Note that with Python 3.15, no need to do that anymore [PEP 686 – Make UTF-8 mode default](https://peps.python.org/pep-0686/)
447
+
448
+
441
449
  ## Packaging the CLI with Build Agents
442
450
  Many of the above CI examples include a step to explicitly install the NeoLoad CLI as part of the
443
451
  build steps. However, if you want the CLI baked into some build agent directly so that it
@@ -1,4 +1,4 @@
1
- FROM python:3.7-alpine
1
+ FROM python:3.12.9-alpine
2
2
 
3
3
  ARG PYPI_VERSION
4
4
 
@@ -68,7 +68,7 @@ jobs:
68
68
  --web-vu 5 \
69
69
  --as-code default.yaml,slas/uat.yaml \
70
70
  --name "Azure pipeline performance regression task $(Build.BuildNumber)" \
71
- --external-url "$(Build.BuildUri)" \
71
+ --external-url "$(Build.Repository.Uri)" \
72
72
  --external-url-label "Azure CI build $(Build.BuildNumber)" \
73
73
  --description "Azure result description" \
74
74
  "My Azure Test With CLI"
@@ -51,7 +51,7 @@ jobs:
51
51
  --web-vu 5 \
52
52
  --as-code default.yaml,slas/uat.yaml \
53
53
  --name "Azure pipeline performance regression task $(Build.BuildNumber)" \
54
- --external-url "$(Build.BuildUri)" \
54
+ --external-url "$(Build.Repository.Uri)" \
55
55
  --external-url-label "Azure CI build $(Build.BuildNumber)" \
56
56
  --description "Azure result description" \
57
57
  "My Azure Test With CLI"
@@ -21,7 +21,7 @@ jobs:
21
21
  runs-on: ubuntu-latest
22
22
  steps:
23
23
  - name: Checkout local code
24
- uses: actions/checkout@v3
24
+ uses: actions/checkout@v4
25
25
 
26
26
  - name: "Install NeoLoad CLI"
27
27
  run: pip3 install -U neoload
@@ -18,7 +18,7 @@ plugin_folder = os.path.join(os.path.dirname(__file__), 'commands')
18
18
  sys.stdout = sys.__stdout__
19
19
 
20
20
 
21
- class NeoLoadCLI(click.MultiCommand):
21
+ class NeoLoadCLI(click.Group):
22
22
  def list_commands(self, ctx):
23
23
  """Dynamically get the list of commands."""
24
24
  rv = []
@@ -1,15 +1,16 @@
1
1
  import os
2
-
2
+ import zipfile
3
3
  import click
4
-
4
+ import urllib.parse as urlparse
5
5
  from commands import test_settings
6
+ from pathlib import Path
6
7
  from neoload_cli_lib import user_data, tools, rest_crud, neoLoad_project
7
8
 
8
9
 
9
10
  @click.command()
10
11
  @click.argument("command", required=True, type=click.Choice(['up', 'upload', 'meta']))
11
12
  @click.option("--path", "-p", type=click.Path(exists=True), default=os.getcwd(),
12
- help="path of project folder, zip or yml file. . is default value")
13
+ help="Path of project folder, zip or yml file. . is default value")
13
14
  @click.option("--save", "-s", type=click.Path(exists=False),
14
15
  help="Path to a (non-existent) file ending in .zip to preserve what was uploaded")
15
16
  @click.argument("name_or_id", type=str, required=False)
@@ -18,10 +19,8 @@ def cli(command, name_or_id, path, save):
18
19
  rest_crud.set_current_command()
19
20
  if not name_or_id or name_or_id == "cur":
20
21
  name_or_id = user_data.get_meta(test_settings.meta_key)
21
-
22
22
  if not tools.is_id(name_or_id):
23
23
  name_or_id = test_settings.__resolver.resolve_name(name_or_id)
24
-
25
24
  if command[:2] == "up":
26
25
  upload(path, name_or_id, save)
27
26
  elif command == "meta":
@@ -29,6 +28,30 @@ def cli(command, name_or_id, path, save):
29
28
  user_data.set_meta(test_settings.meta_key, name_or_id)
30
29
  rest_crud.set_current_sub_command(command)
31
30
 
31
+ def has_password_in_zip_project(zip_path) -> bool:
32
+ with zipfile.ZipFile(zip_path, 'r') as zip_file:
33
+ for file_name in zip_file.namelist():
34
+ if file_name.endswith('.nlp'):
35
+ with zip_file.open(file_name, 'r') as nlp_file:
36
+ return has_password_in_nlp(nlp_file)
37
+ return False
38
+
39
+
40
+ def has_password_in_folder_project(folder_path) -> bool:
41
+ for root, dirs, files in os.walk(folder_path):
42
+ for file in files:
43
+ if file.endswith(".nlp"):
44
+ with open(Path(root) / file, 'rb') as nlp_file:
45
+ return has_password_in_nlp(nlp_file)
46
+ return False
47
+
48
+
49
+ def has_password_in_nlp(nlp_file) -> bool:
50
+ for line in nlp_file:
51
+ if b'project.password.hash=' in line:
52
+ return True
53
+ return False
54
+
32
55
 
33
56
  #TODO: pre-validate with 'neoload validate' functionality, but..
34
57
  #TODO: provide a --skip-validation option
@@ -36,6 +59,13 @@ def cli(command, name_or_id, path, save):
36
59
  #TODO: fix validate to recurse through all includes; create unique file list map (avoid recursive references)
37
60
 
38
61
  def upload(path, settings_id, save):
62
+ path = Path(path)
63
+ has_password = has_password_in_zip_project(path) if path.suffix == '.zip' else has_password_in_folder_project(path)
64
+ if has_password:
65
+ print("Your project has a password, please make sure your password is set in the test: " +
66
+ urlparse.urljoin(user_data.get_user_data().get_frontend_url(), "/#!test-settings/" + settings_id))
67
+
68
+ # Always call the upload_project method
39
69
  neoLoad_project.upload_project(path, get_endpoint(settings_id), save)
40
70
 
41
71
 
@@ -224,7 +224,7 @@ def parse_source_data_spec(json_in, model, report_type, name):
224
224
 
225
225
  def process_final_output(template, template_text, json_data):
226
226
  if template_text is None or template_text == "":
227
- return json.dumps(json_data)
227
+ return json.dumps(json_data, ensure_ascii=False)
228
228
  else:
229
229
  dirname = os.path.dirname(os.path.abspath(template))
230
230
  loader = jinja2.FileSystemLoader(searchpath=dirname)
@@ -6,10 +6,9 @@ import logging
6
6
  import gitignorefile
7
7
 
8
8
  from neoload_cli_lib import rest_crud, tools, cli_exception
9
- import shutil
10
9
 
11
10
  not_to_be_included = ['recorded-requests/', 'recorded-responses/', 'recorded-screenshots/', '.git/', '.svn/',
12
- 'results/','.config/','.neoload_cli.yaml',
11
+ 'results/', '.config/', '.neoload_cli.yaml',
13
12
  'comparative-summary/', 'reports/', '/recorded-artifacts/']
14
13
 
15
14
 
@@ -65,7 +64,10 @@ def upload_project(path, endpoint, save=None):
65
64
  filename += '.zip'
66
65
  file = zip_dir(path,save)
67
66
 
68
- display_project(rest_crud.post_binary_files_storage(endpoint, file, filename))
67
+ response = rest_crud.post_binary_files_storage(endpoint, file, filename)
68
+ display_project(response)
69
+ file.close()
70
+
69
71
 
70
72
  def display_project(res):
71
73
  if 299 > res.status_code > 199:
@@ -9,7 +9,7 @@ from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor
9
9
  from tqdm import tqdm
10
10
 
11
11
  from neoload_cli_lib import user_data, cli_exception, tools
12
- from version import __version__
12
+ from version_manager import __version__
13
13
 
14
14
  from requests.adapters import HTTPAdapter
15
15
  from requests.packages.urllib3.util.retry import Retry
@@ -169,6 +169,7 @@ def __create_url(endpoint: str):
169
169
 
170
170
 
171
171
  def __handle_error(response):
172
+ response.encoding = response.apparent_encoding
172
173
  status_code = response.status_code
173
174
  if status_code > 299:
174
175
  request = response.request
@@ -6,10 +6,10 @@ import sys
6
6
  import click
7
7
  from click import ClickException
8
8
  from termcolor import cprint
9
+ from version_manager import __version__
9
10
 
10
11
  from neoload_cli_lib import rest_crud, user_data, config_global, filtering
11
12
 
12
- from version import __version__
13
13
 
14
14
  __regex_id = re.compile('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
15
15
  __regex_mongodb_id = re.compile('[a-f\\d]{24}', re.IGNORECASE)
@@ -0,0 +1 @@
1
+ __version__ = "1.3.17"
@@ -0,0 +1,4 @@
1
+ try:
2
+ from version import __version__
3
+ except ImportError as e:
4
+ __version__=None
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: neoload
3
- Version: 1.3.14.dev3
3
+ Version: 1.3.17
4
4
  Summary: A command-line native utility for launching and observing NeoLoad performance tests
5
5
  Home-page: https://github.com/Neotys-Labs/neoload-cli
6
6
  Author: Neotys
@@ -28,8 +28,16 @@ Requires-Dist: pyparsing
28
28
  Requires-Dist: simplejson
29
29
  Requires-Dist: colorama
30
30
  Requires-Dist: importlib-resources
31
+ Dynamic: author
32
+ Dynamic: description
33
+ Dynamic: description-content-type
34
+ Dynamic: home-page
35
+ Dynamic: license
36
+ Dynamic: license-file
37
+ Dynamic: requires-dist
38
+ Dynamic: summary
31
39
 
32
- # NeoLoad CLI [![Build Status](https://github.com/Neotys-Labs/neoload-cli/workflows/Python%20package/badge.svg?branch=master)](https://github.com/Neotys-Labs/neoload-cli/actions?query=workflow%3A%22Python+package%22+branch%3A%22master%22)
40
+ # NeoLoad CLI [![Python package](https://github.com/Neotys-Labs/neoload-cli/actions/workflows/python-package.yml/badge.svg?branch=master)](https://github.com/Neotys-Labs/neoload-cli/actions/workflows/python-package.yml)
33
41
 
34
42
  ## Overview
35
43
 
@@ -469,6 +477,14 @@ neoload wait cur
469
477
 
470
478
  [An example for Jenkins pipeline is found here.](examples/pipelines/jenkins/Jenkinsfile_slafails)
471
479
 
480
+ ## Troubleshooting
481
+ ### Windows and non UTF-8 characters
482
+ Windows use default encoding as ASCII, but the NeoLoad CLI needs UTF-8 encoding.\
483
+ Before running some commands like `neoload report` on windows, you need to set environment variable `set PYTHONUTF8=1`\
484
+ More info [here](https://docs.python.org/3/using/windows.html#utf-8-mode) and [here](https://docs.python.org/3/library/os.html#utf8-mode).
485
+ Note that with Python 3.15, no need to do that anymore [PEP 686 – Make UTF-8 mode default](https://peps.python.org/pep-0686/)
486
+
487
+
472
488
  ## Packaging the CLI with Build Agents
473
489
  Many of the above CI examples include a step to explicitly install the NeoLoad CLI as part of the
474
490
  build steps. However, if you want the CLI baked into some build agent directly so that it
@@ -35,6 +35,7 @@ examples/pipelines/jenkins/Jenkinsfile_slafails
35
35
  neoload/__init__.py
36
36
  neoload/__main__.py
37
37
  neoload/version.py
38
+ neoload/version_manager.py
38
39
  neoload.egg-info/PKG-INFO
39
40
  neoload.egg-info/SOURCES.txt
40
41
  neoload.egg-info/dependency_links.txt
@@ -114,6 +115,7 @@ tests/commands/docker/test_docker_connections.py
114
115
  tests/commands/docker/test_docker_hooks.py
115
116
  tests/commands/fastfail/test_fastfail_slas.py
116
117
  tests/commands/project/test_upload.py
118
+ tests/commands/project/test_upload_with_password.py
117
119
  tests/commands/report/test_report.py
118
120
  tests/commands/report/test_report_json_output.py
119
121
  tests/commands/report/test_report_templates.py
@@ -170,6 +172,7 @@ tests/neoload_projects/.nlignore
170
172
  tests/neoload_projects/broken_yaml.yaml
171
173
  tests/neoload_projects/empty.yaml
172
174
  tests/neoload_projects/example_1.zip
175
+ tests/neoload_projects/example_2.zip
173
176
  tests/neoload_projects/invalid_to_schema.yaml
174
177
  tests/neoload_projects/simpledemo.yml
175
178
  tests/neoload_projects/example_1/.gitlab-ci.yml
@@ -0,0 +1,3 @@
1
+ pytest
2
+ pytest-datafiles
3
+ pytest-mock
@@ -16,7 +16,7 @@ setup(
16
16
  'neoload=neoload.__main__:cli'
17
17
  ]
18
18
  },
19
- setup_requires=['setuptools_scm==5.0.1'],
19
+ setup_requires=['setuptools_scm==9.2.2'],
20
20
  use_scm_version={
21
21
  'write_to': 'neoload/version.py',
22
22
  'write_to_template': '__version__ = "{version}"',
@@ -0,0 +1,49 @@
1
+ import os
2
+ import zipfile
3
+
4
+ from commands.project import has_password_in_zip_project, has_password_in_folder_project, upload
5
+
6
+ nlp_content_with_password = """project.name=test
7
+ project.version=8.10
8
+ project.password.hash=12vsXUgFbgL2g7u5aMuRsyhimKuEIk+jMXVD5pbkfo0=$0
9
+ """
10
+ nlp_content = """project.name=test
11
+ project.version=8.10
12
+ """
13
+
14
+
15
+ def create_neoload_project_zip(tmp_path, with_password):
16
+ zip_path = tmp_path / "test.zip"
17
+ with zipfile.ZipFile(zip_path, 'w') as zipf:
18
+ zipf.writestr('test.nlp', nlp_content_with_password if with_password else nlp_content)
19
+ return zip_path
20
+
21
+
22
+ def create_neoload_project_folder(tmp_path, with_password):
23
+ folder_path = tmp_path / "test_project"
24
+ if not folder_path.exists():
25
+ os.mkdir(folder_path)
26
+ with open(folder_path / "test.nlp", "w") as f:
27
+ f.write(nlp_content_with_password if with_password else nlp_content)
28
+ return folder_path
29
+
30
+
31
+ def test_has_password_in_zip_project(tmp_path):
32
+ zip_with_password = create_neoload_project_zip(tmp_path, True)
33
+ assert has_password_in_zip_project(zip_with_password) == True
34
+ zip_project = create_neoload_project_zip(tmp_path, False)
35
+ assert has_password_in_zip_project(zip_project) == False
36
+
37
+
38
+ def test_has_password_in_folder_project(tmp_path):
39
+ folder_with_password = create_neoload_project_folder(tmp_path, True)
40
+ assert has_password_in_folder_project(folder_with_password) == True
41
+ folder_project = create_neoload_project_folder(tmp_path, False)
42
+ assert has_password_in_folder_project(folder_project) == False
43
+
44
+
45
+ def test_upload_with_password(mocker, tmp_path):
46
+ zip_with_password = create_neoload_project_zip(tmp_path, True)
47
+ mock_upload_project = mocker.patch('commands.project.neoLoad_project.upload_project', return_value=9)
48
+ upload(zip_with_password, "test_id", "pathToSave/file.zip")
49
+ mock_upload_project.assert_called_once_with(zip_with_password, 'v2/tests/test_id/project', 'pathToSave/file.zip')
@@ -2,6 +2,7 @@ import json
2
2
  from datetime import datetime, timezone
3
3
  from requests import Response
4
4
  from neoload_cli_lib import rest_crud, user_data
5
+ from datetime import timezone
5
6
 
6
7
 
7
8
  def assert_success(result):
@@ -235,8 +235,8 @@ function getMinMaxAvgMedianStdDev(data, plot) {
235
235
  <div style="float:left;width:80%;">
236
236
  <h1 style="text-align:left;">#3</h1>
237
237
  </div>
238
- <div style="float:right;width:20%;padding-top:0.75em;">
239
- <div class="logo" style="margin:auto auto;transform: scale(0.5);">&nbsp;</div>
238
+ <div style="float:right;width:160px;padding-top:0.75em;">
239
+ <svg fill="hsla(210, 100%, 30%, 1)" viewBox="0 0 1366 281.16"><polygon points="34.84 227.65 0 192.81 52.38 140.43 0.39 88.44 35.23 53.6 122.06 140.43 34.84 227.65"></polygon><polygon points="88.34 281.16 53.51 246.32 140.73 159.1 227.56 245.93 192.72 280.76 140.73 228.78 88.34 281.16"></polygon><polygon points="140.43 122.06 53.6 35.23 88.44 0.4 140.43 52.39 192.81 0 227.65 34.84 140.43 122.06"></polygon><polygon points="468.86 31.92 289.87 31.92 289.87 65.1 361.88 65.1 361.88 248.26 396.85 248.26 396.85 65.1 468.86 65.1 468.86 31.92"></polygon><path d="M475.27,106.83l-3.22-18.74H441V248.26h35v-106a54.21,54.21,0,0,1,21.62-16.84,75.54,75.54,0,0,1,31.27-6.53h6.27V85.1h-6.27C507.51,85.1,489.53,92.4,475.27,106.83Z"></path><rect x="553.54" y="88.09" width="34.97" height="160.17"></rect><rect x="552.49" y="26.54" width="37.06" height="37.06"></rect><path d="M698.43,84C647.13,84,607,120.54,607,167.2v.61c0,46.15,40,82.29,91.14,82.29,18.74,0,34.61-3.73,48.5-11.42l-.39-.35c-.6-.55-1.21-1.1-1.77-1.7h0a81.16,81.16,0,0,1-15.07-23.18,60.44,60.44,0,0,1-29.23,7.27c-31.35,0-55-23-55-53.52v-.61c0-29.67,23.27-52.91,53-52.91A60.63,60.63,0,0,1,729.62,122a88.74,88.74,0,0,1,17.79-26.71C733.54,87.67,717.5,84,698.43,84Z"></path><path d="M818.2,85.1a78.28,78.28,0,0,0-28.15,5.3,71,71,0,0,0-24.38,15.71,77.17,77.17,0,0,0-17,26.17c-4.26,10.44-6.42,22.77-6.42,36.66a103.82,103.82,0,0,0,5,32.88A67.86,67.86,0,0,0,788.79,245c10.61,4.12,23.26,6.21,37.61,6.21a149.67,149.67,0,0,0,16.64-.92c5.44-.61,10.57-1.37,15.23-2.27a124.88,124.88,0,0,0,12.55-3,63.44,63.44,0,0,0,8.14-3l-4.83-28.9a113,113,0,0,1-17.5,4.91,123.43,123.43,0,0,1-25.5,2.46c-15.86,0-28.14-3.59-36.52-10.68s-13.21-17.25-14.26-30.18l-.06-.71H889.18c.18-1.84.32-3.94.42-6.24.1-2.64.15-4.87.15-6.83,0-26.74-6.36-47.12-18.9-60.56S840.6,85.1,818.2,85.1Zm34.7,68H780.57l.1-.74a62.7,62.7,0,0,1,3.5-13.87,38.93,38.93,0,0,1,7.21-12.1,34.87,34.87,0,0,1,27.13-11.8,34.91,34.91,0,0,1,14.93,3,31.25,31.25,0,0,1,10.63,8.1,35.47,35.47,0,0,1,6.59,12.12,48,48,0,0,1,2.24,14.69Z"></path><path d="M994.06,85.1c-19.22,0-36.78,7.46-52.29,22.18l-3.3-19.19H907.4V248.26h35V144.16C956.61,126.79,971.78,118,987.48,118c19.77,0,29,10.35,29,32.57v97.71h35V147.56c0-17.61-5.14-32.53-15.28-44.37C1025.86,91.19,1011.7,85.1,994.06,85.1Z"></path><path d="M1123.54,49.87l-63.36,62v7.32h28.39v88.74c0,28.34,16.43,43.33,47.51,43.33a61.19,61.19,0,0,0,28.69-7l2.09-1.09V214.78h-6.8l-.76.34c-13.3,5.91-24.77,5.1-31.23,2.38-3-1.31-4.53-5.33-4.53-12V119.18h43.32V88.09h-43.32Z"></path><rect x="1188.39" y="88.09" width="34.97" height="160.17"></rect><rect x="1187.35" y="26.54" width="37.06" height="37.06"></rect><path d="M1356,173a47.6,47.6,0,0,0-24.31-15.16l-26.46-6.94a119.71,119.71,0,0,1-21.89-7.8c-6.51-3.16-7.27-7-7.27-9.59,0-4.25,2.38-7.78,7.27-10.79,5.42-3.34,14.23-5,26.19-5,12.17,0,24.83,2.72,37.65,8.07l.72.3h6.76V94.66l-2.54-.94a141.69,141.69,0,0,0-49.76-8.62c-18.21,0-32.89,4.75-43.64,14.11-10.9,9.5-16.42,22-16.42,37,0,11.14,3.47,20.48,10.32,27.76A51.06,51.06,0,0,0,1277,178.49l26.33,7.06a130.83,130.83,0,0,1,21.59,7.61c7,3.31,7,6.66,7,7.76,0,7.49-3,17.45-29.28,17.45a99,99,0,0,1-51.2-13.8l-.92-.54h-6.45v32.18l2,1.11c16.84,9.24,35.72,13.93,56.11,13.93,20.65,0,36.57-4.53,47.3-13.45,10.94-9.1,16.49-20.43,16.49-33.68C1366,191.13,1362.63,180.65,1356,173Z"></path></svg>
240
240
  </div>
241
241
  </div>
242
242
 
@@ -564,12 +564,6 @@ table.legend, table.legend > tbody > tr > td {
564
564
  border: 0px;
565
565
  padding:0px;
566
566
  }
567
-
568
- .logo {
569
- width: 300px;
570
- height: 74px;
571
- background-image: url(data:image/jpeg;base64,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);
572
- }
573
567
  </style>
574
568
  </body>
575
569
  </html>