summaryrefslogtreecommitdiffstats
path: root/testapi
diff options
context:
space:
mode:
Diffstat (limited to 'testapi')
-rw-r--r--testapi/3rd_party/static/testapi-ui/assets/css/style.css49
-rw-r--r--testapi/docker/Dockerfile7
-rw-r--r--testapi/docs/developer/devguide/images/CAS-sequence.jpgbin0 -> 11785 bytes
-rw-r--r--testapi/docs/developer/devguide/testapi-client-import.rst974
-rw-r--r--testapi/docs/developer/devguide/testapi-client.rst858
-rw-r--r--testapi/docs/developer/devguide/web-portal.rst114
-rw-r--r--testapi/docs/internship/webportal.rst169
-rw-r--r--testapi/opnfv_testapi/common/check.py12
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/authenticateFalseSpec.js76
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/deployResultsControllerSpec.js2
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js36
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js54
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js4
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/scenarioControllerSpec.js45
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js42
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/testCasesControllerSpec.js25
-rw-r--r--testapi/opnfv_testapi/ui/Gruntfile.js16
-rw-r--r--testapi/opnfv_testapi/ui/components/pods/pods.html16
-rw-r--r--testapi/opnfv_testapi/ui/components/pods/podsController.js39
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html16
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js68
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/projects.html16
-rw-r--r--testapi/opnfv_testapi/ui/components/projects/projectsController.js60
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html16
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js93
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenarios.html16
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js74
-rw-r--r--testapi/opnfv_testapi/ui/package.json1
-rw-r--r--testapi/requirements.txt3
-rw-r--r--testapi/testapi-client/etc/client.creds3
-rw-r--r--testapi/testapi-client/setup.cfg4
-rw-r--r--testapi/testapi-client/testapiclient/cli/deployresults.py12
-rw-r--r--testapi/testapi-client/testapiclient/cli/pods.py12
-rw-r--r--testapi/testapi-client/testapiclient/cli/projects.py15
-rw-r--r--testapi/testapi-client/testapiclient/cli/results.py97
-rw-r--r--testapi/testapi-client/testapiclient/cli/scenarios.py147
-rw-r--r--testapi/testapi-client/testapiclient/cli/testcases.py19
-rw-r--r--testapi/testapi-client/testapiclient/client/__init__.py0
-rw-r--r--testapi/testapi-client/testapiclient/client/base.py23
-rw-r--r--testapi/testapi-client/testapiclient/client/deploy_results.py28
-rw-r--r--testapi/testapi-client/testapiclient/client/pods.py31
-rw-r--r--testapi/testapi-client/testapiclient/client/projects.py35
-rw-r--r--testapi/testapi-client/testapiclient/client/results.py28
-rw-r--r--testapi/testapi-client/testapiclient/client/scenarios.py177
-rw-r--r--testapi/testapi-client/testapiclient/client/testcases.py36
-rw-r--r--testapi/testapi-client/testapiclient/models/__init__.py0
-rw-r--r--testapi/testapi-client/testapiclient/models/deployresult.py17
-rw-r--r--testapi/testapi-client/testapiclient/models/pods.py6
-rw-r--r--testapi/testapi-client/testapiclient/models/project.py4
-rw-r--r--testapi/testapi-client/testapiclient/models/result.py16
-rw-r--r--testapi/testapi-client/testapiclient/models/scenario.py37
-rw-r--r--testapi/testapi-client/testapiclient/models/testcase.py20
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_app.py50
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_deployresults_client.py81
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_pod_client.py89
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_project_client.py111
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_results.py98
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_results_client.py78
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_scenario_client.py104
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_scenario_custom_client.py106
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_scenario_installer_client.py86
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_scenario_project_client.py104
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_scenario_score_client.py53
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_scenario_trust_indicator_client.py53
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_scenario_version_client.py96
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_testcase_client.py118
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/utils.py4
-rw-r--r--testapi/testapi-client/testapiclient/utils/clientmanager.py6
68 files changed, 4557 insertions, 348 deletions
diff --git a/testapi/3rd_party/static/testapi-ui/assets/css/style.css b/testapi/3rd_party/static/testapi-ui/assets/css/style.css
index fb21399..2b20d6b 100644
--- a/testapi/3rd_party/static/testapi-ui/assets/css/style.css
+++ b/testapi/3rd_party/static/testapi-ui/assets/css/style.css
@@ -292,4 +292,53 @@ json-tree .key {
json-tree .leaf-value{
word-break: normal!important;
+}
+
+#toast {
+ visibility: hidden;
+ min-width: 250px;
+ margin-left: -125px;
+ color: #fff;
+ text-align: center;
+ border-radius: 10px;
+ padding: 16px;
+ position: fixed;
+ z-index: 9999;
+ left: 50%;
+ bottom: 30px;
+}
+
+#toast.error{
+ background-color: #B03838;
+}
+
+#toast.success{
+ background-color: #1A911E;
+}
+
+#toast.show {
+ visibility: visible;
+
+ -webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
+ animation: fadein 0.5s, fadeout 0.5s 2.5s;
+}
+
+@-webkit-keyframes fadein {
+ from {bottom: 0; opacity: 0;}
+ to {bottom: 30px; opacity: 1;}
+}
+
+@keyframes fadein {
+ from {bottom: 0; opacity: 0;}
+ to {bottom: 30px; opacity: 1;}
+}
+
+@-webkit-keyframes fadeout {
+ from {bottom: 30px; opacity: 1;}
+ to {bottom: 0; opacity: 0;}
+}
+
+@keyframes fadeout {
+ from {bottom: 30px; opacity: 1;}
+ to {bottom: 0; opacity: 0;}
} \ No newline at end of file
diff --git a/testapi/docker/Dockerfile b/testapi/docker/Dockerfile
index bbf12fc..dccc162 100644
--- a/testapi/docker/Dockerfile
+++ b/testapi/docker/Dockerfile
@@ -40,7 +40,7 @@ python-pip \
crudini \
--no-install-recommends
-RUN pip install --upgrade pip requests
+RUN pip install --upgrade requests
RUN git config --global http.sslVerify false
RUN git clone https://gerrit.opnfv.org/gerrit/releng-testresults /home/releng-testresults
@@ -48,5 +48,10 @@ RUN git clone https://gerrit.opnfv.org/gerrit/releng-testresults /home/releng-te
WORKDIR /home/releng-testresults/testapi
RUN pip install -r requirements.txt
+# bugfix
+# SSLError: hostname 'identity.linuxfoundation.org' doesn't match 'c.sni.fastly.net'
+# hope it is a temprary, try to fix it in upstream python-cas lib
+RUN sed -i '152,152s/)/,\ verify=False)/g' /usr/local/lib/python2.7/dist-packages/cas.py
+
RUN python setup.py install
CMD ["bash", "docker/start-server.sh"]
diff --git a/testapi/docs/developer/devguide/images/CAS-sequence.jpg b/testapi/docs/developer/devguide/images/CAS-sequence.jpg
new file mode 100644
index 0000000..a624871
--- /dev/null
+++ b/testapi/docs/developer/devguide/images/CAS-sequence.jpg
Binary files differ
diff --git a/testapi/docs/developer/devguide/testapi-client-import.rst b/testapi/docs/developer/devguide/testapi-client-import.rst
new file mode 100644
index 0000000..c6d7311
--- /dev/null
+++ b/testapi/docs/developer/devguide/testapi-client-import.rst
@@ -0,0 +1,974 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) 2017 ZTE Corp.
+
+=====================
+TestAPI client import
+=====================
+
+**Python module to communicate with the TestAPI Server**
+
+This project aims to provide a python module which can
+communicate with the TestAPI Server. The user can use this client
+to fetch/post/modify the resources on the TestAPI Server.
+
+Usage
+-----
+
+Pod
+^^^
+
+GET
+"""
+
+Get a list of all the declared pods from the TestAPI server.
+
+.. code-block:: shell
+
+ from testapiclient.client import pods
+
+ pod_client = pods.PodsClient()
+ pod_client.get()
+
+The user can filter the results by the name attribute. Backend will
+use a regular expression to find the list of pods which are
+related to given name.
+
+.. code-block:: shell
+
+ from testapiclient.client import pods
+
+ pod_client = pods.PodsClient()
+ pod_client.get(name='pod1')
+
+.. NOTE::
+ Response format: [{"_id": "", "creator": "", "role": "", "name": "",
+ "details": "", "mode": "", "creation_date": ""}]
+
+
+GET ONE
+"""""""
+
+Get a specific pod by its name.
+
+.. code-block:: shell
+
+ from testapiclient.client import pods
+
+ pod_client = pods.PodsClient()
+ pod_client.get_one('name')
+
+.. NOTE::
+ Response format: {"_id": "", "creator": "", "role": "", "name": "",
+ "details": "", "mode": "", "creation_date": ""}
+
+CREATE
+""""""
+This method used to create a project on the server.
+The user should provide the user parameter and the password
+parameter while initiating the PodsClient.
+
+Input for the function :
+
+ * pod-json : Json object of the project
+
+.. NOTE::
+ pod-json-schema - '{"role": "", "name": "", "details": "", "mode": ""}'
+
+ * role should be either "community-ci" or "production-ci"
+ * mode should be either "metal" or "virtual"
+
+.. code-block:: shell
+
+ from testapiclient.client import pods
+
+ pod_client = pods.PodsClient(user='test', password='pass')
+ pod_client.create({'name': 'test-api', 'mode':'metal',
+ 'role':'community_ci', 'details':''})
+
+
+Project
+^^^^^^^
+
+GET
+"""
+
+Get a list of all the declared projects from the TestAPI server.
+
+.. code-block:: shell
+
+ from testapiclient.client import projects
+
+ project_client = projects.ProjectsClient()
+ project_client.get()
+
+User can filter the results by the name attribute. Backend will
+use a regular expression to find the list of projects which are
+related to given name.
+
+.. code-block:: shell
+
+ from testapiclient.client import projects
+
+ project_client = projects.ProjectsClient()
+ project_client.get(name='project1')
+
+.. NOTE::
+ Response format: [{"_id": "", "creator": "", "description": "",
+ "name": "", "creation_date": ""}]
+
+GET ONE
+"""""""
+
+Get a specific project by its name.
+
+.. code-block:: shell
+
+ from testapiclient.client import projects
+
+ project_client = projects.ProjectsClient()
+ project_client.get_one('name')
+
+.. NOTE::
+ Response format: {"_id": "", "creator": "", "description": "",
+ "name": "", "creation_date": ""}
+
+CREATE
+""""""
+
+This method used to create a project on the server.
+The user should provide the user parameter and the password
+parameter while initiating the ProjectsClient.
+
+Input for the function :
+
+ * project-json : Json object of the project
+
+.. NOTE::
+ project-json schema - '{"description": "", "name": ""}'
+
+.. code-block:: shell
+
+ from testapiclient.client import projects
+
+ project_client = projects.ProjectsClient(user='test', password='pass')
+ project_client.create({'name': 'functest', 'description':'sample text'}
+
+UPDATE
+""""""
+
+This method used to update an existing project on the server.
+The user should provide the user parameter and the password
+parameter while initiating the ProjectsClient.
+
+Input for the function :
+
+ * project-name: name of the project which user want to update.
+ * project-json: Json object of the project
+
+.. NOTE::
+ project-json schema - '{"description": "", "name": ""}'
+
+.. code-block:: shell
+
+ from testapiclient.client import projects
+
+ project_client = projects.ProjectsClient(user='test', password='pass')
+ project_client.update('functest', {'name': 'functest',
+ 'description':'updated text'})
+
+DELETE
+""""""
+
+This method used to delete an existing project on the server.
+The user should provide the user parameter and the password
+parameter while initiating the ProjectsClient.
+
+Input for the function :
+
+ * project-name: name of the project which user want to delete.
+
+.. code-block:: shell
+
+ from testapiclient.client import projects
+
+ project_client = projects.ProjectsClient(user='test', password='pass')
+ project_client.delete('functest')
+
+
+Testcase
+^^^^^^^^
+
+GET
+"""
+
+Get a list of all the declared testcases under a project
+from the TestAPI server.
+
+Input for the function :
+
+ * project_name : Name of the project
+
+.. code-block:: shell
+
+ from testapiclient.client import testcases
+
+ testcase_client = testcases.TestcasesClient()
+ testcase_client.get(project_name='functest')
+
+
+.. NOTE::
+ Response format: [{ "project_name": "functest", "run": "",
+ "description": "", "tags": "", "creation_date": "",
+ "dependencies": "", "tier": "", "trust": "", "blocking": "",
+ "name": "", "ci_loop": "", "url": "", "version": "",
+ "criteria": "", "domains": "", "_id": "", "catalog_description": ""}]
+
+GET ONE
+"""""""
+
+Get a specific testcase by its name and project name.
+
+.. code-block:: shell
+
+ from testapiclient.client import testcases
+
+ testcase_client = testcases.TestcasesClient()
+ testcase_client.get_one(project_name='functest', case_name='name')
+
+.. NOTE::
+ Response format: { "project_name": "functest", "run": "",
+ "description": "", "tags": "", "creation_date": "",
+ "dependencies": "", "tier": "", "trust": "", "blocking": "",
+ "name": "", "ci_loop": "", "url": "", "version": "",
+ "criteria": "", "domains": "", "_id": "", "catalog_description": ""}
+
+CREATE
+""""""
+
+This method used to create a testcase on the server.
+The user should provide the user parameter and the password
+parameter while initiating the TestcasesClient.
+
+Input for the function :
+ * project_name : Project name
+ * testcase_json : Json object of the testcase
+
+.. NOTE::
+ testcase_json schema - '{ "run": "", "description": "", "tags": "",
+ "dependencies": "", "tier": "", "trust": "", "blocking": "",
+ "name": "", "ci_loop": "", "url": "", "version": "",
+ "criteria": "", "domains": "", "catalog_description": ""}'
+
+.. code-block:: shell
+
+ from testapiclient.client import testcases
+
+ testcase_client = testcases.TestcasesClient(user='test', password='pass')
+ testcase_client.create(project_name, testcase_json)
+
+UPDATE
+""""""
+
+This method used to update an existing testcase on the server.
+The user should provide the user parameter and the password
+parameter while initiating the TestcasesClient.
+
+Input for the function :
+ * project_name : Project name
+ * testcase_name: name of the testcase which user want to update.
+ * testcase_json: Json object of the testcase
+
+.. NOTE::
+ testcase-json schema - '{ "run": "", "description": "", "tags": "",
+ "dependencies": "", "tier": "", "trust": "", "blocking": "",
+ "name": "", "ci_loop": "", "url": "", "version": "",
+ "criteria": "", "domains": "", "catalog_description": ""}'
+
+.. code-block:: shell
+
+ from testapiclient.client import testcases
+
+ testcase_client = testcases.TestcasesClient(user='test', password='pass')
+ testcase_client.update(project_name, testcase_name, testcase_json)
+
+DELETE
+""""""
+
+This method used to delete an existing testcase on the server.
+The user should provide the user parameter and the password
+parameter while initiating the TestcasesClient.
+
+Input for the function :
+
+ * project_name: name of the project
+ * testcase_name: name of the testcase which user want to delete.
+
+.. code-block:: shell
+
+ from testapiclient.client import testcases
+
+ testcase_client = testcases.TestcasesClient(user='test', password='pass')
+ testcase_client.delete(project_name, testcase_name)
+
+
+Result
+^^^^^^^
+
+GET
+"""
+
+Get a list of all the declared results from the TestAPI server.
+
+.. code-block:: shell
+
+ from testapiclient.client import results
+
+ result_client = results.ResultsClient()
+ result_client.get()
+
+User can filter the results by using some attributes.
+
+.. NOTE::
+ List of search attributes.
+
+ * case : Search results using tesetcase
+ * build-tag : Search results using build tag
+ * from : Search results using from date
+ * last : Search results using last date
+ * scenario : Search results using scenario
+ * period : Search results using period
+ * project : Search results using project
+ * to : Search results using to
+ * version : Search results using version
+ * criteria : Search results using criteria
+ * installer : Search results using installer
+ * pod : Search results using pod
+ * page : Search results using page
+
+.. code-block:: shell
+
+ from testapiclient.client import results
+
+ result_client = results.ResultsClient()
+ result_client.get(pod='pod1', project='project1')
+
+
+.. NOTE::
+ Response format: [{ "project_name": "", "scenario": "",
+ "stop_date": "", "case_name": "", "build_tag": "",
+ "version": "", "pod_name": "", "criteria": "",
+ "installer": "", "start_date": "", "details": ""}]
+
+GET ONE
+"""""""
+
+Get a specific result by its id.
+
+.. code-block:: shell
+
+ from testapiclient.client import results
+
+ result_client = results.ResultsClient()
+ result_client.get_one(result_id)
+
+.. NOTE::
+ Response format: { "project_name": "", "scenario": "",
+ "stop_date": "", "case_name": "", "build_tag": "",
+ "version": "", "pod_name": "", "criteria": "",
+ "installer": "", "start_date": "", "details": ""}
+
+CREATE
+""""""
+
+This method used to create a result on the server.
+The user should provide a valid token to run this method.
+Read testapi-client.rst to more details.
+
+Input for the function :
+ * result_json : Json object of the result
+
+.. NOTE::
+ result_json schema - '{ "project_name": "", "scenario": "",
+ "stop_date": "", "case_name": "", "build_tag": "",
+ "version": "", "pod_name": "", "criteria": "",
+ "installer": "", "start_date": "", "details": ""}'
+
+.. code-block:: shell
+
+ from testapiclient.client import results
+
+ result_client = results.ResultsClient()
+ result_client.create(result_json)
+
+DeployResult
+^^^^^^^^^^^^
+
+GET
+"""
+
+Get a list of all the declared deploy results from the TestAPI server.
+
+.. code-block:: shell
+
+ from testapiclient.client import deploy_results
+
+ deploy_result_client = deploy_results.DeployResultsClient()
+ deploy_result_client.get()
+
+User can filter the deploy results by using some attributes.
+
+.. NOTE::
+ List of search attributes.
+
+ * job-name : Search results using job
+ * build_id : Search results using build id
+ * from : Search results using from date
+ * last : Search results using last date
+ * scenario : Search results using scenario
+ * period : Search results using period
+ * to : Search results using to
+ * version : Search results using version
+ * criteria : Search results using criteria
+ * installer : Search results using installer
+ * pod_name : Search results using pod
+ * page : Search results using page
+
+.. code-block:: shell
+
+ from testapiclient.client import deploy_results
+
+ deploy_result_client = deploy_results.DeployResultsClient()
+ deploy_result_client.get(scenario='scenario1', installer='installer1')
+
+
+.. NOTE::
+ Response format: [{"build_id": "", "upstream_build_id": "",
+ "scenario": "", "stop_date": "", "start_date": "",
+ "upstream_job_name": "", "version": "", "pod_name": "",
+ "criteria": "", "installer": "", "_id": "", "job_name": "",
+ "details": ""}]
+
+GET ONE
+"""""""
+
+Get a specific deploy result by its id.
+
+.. code-block:: shell
+
+ from testapiclient.client import deploy_results
+
+ deploy_result_client = deploy_results.DeployResultsClient()
+ deploy_result_client.get_one(deploy_result_id)
+
+.. NOTE::
+ Response format: {"build_id": "", "upstream_build_id": "",
+ "scenario": "", "stop_date": "", "start_date": "",
+ "upstream_job_name": "", "version": "", "pod_name": "",
+ "criteria": "", "installer": "", "_id": "", "job_name": "",
+ "details": ""}
+
+CREATE
+""""""
+
+This method used to create a deploy_result on the server.
+The user should provide a valid token to run this method.
+Read testapi-client.rst to more details.
+
+Input for the function :
+ * deploy_result_json : Json object of the deploy_result
+
+.. NOTE::
+ deploy_result_json schema - '{"build_id": "", "upstream_build_id": "",
+ "scenario": "", "stop_date": "", "start_date": "",
+ "upstream_job_name": "", "version": "", "pod_name": "",
+ "criteria": "", "installer": "", "job_name": "",
+ "details": ""}'
+
+.. code-block:: shell
+
+ from testapiclient.client import deploy_results
+
+ deploy_result_client = deploy_results.DeployResultsClient()
+ deploy_result_client.create(deploy_result_json)
+
+Scenario
+^^^^^^^^
+
+GET
+"""
+
+Get a list of all the declared scenarios from the TestAPI server.
+
+.. code-block:: shell
+
+ from testapiclient.client import scenarios
+
+ scenario_client = scenarios.ScenariosClient()
+ scenario_client.get()
+
+User can filter the scenarios by using some attributes.
+
+.. NOTE::
+ List of search attributes.
+
+ * project : Search scenarios using project
+ * installer : Search scenarios using project
+ * version : Search scenarios using project
+ * name: Search scenarios using project
+
+.. code-block:: shell
+
+ from testapiclient.client import scenarios
+
+ scenario_client = scenarios.ScenariosClient()
+ scenario_client.get(name='scenario1')
+
+.. NOTE::
+ Response format: [{ "installers": [], "_id": "", "creation_date": "",
+ "name": "", "creator": ""}]
+
+GET ONE
+"""""""
+
+Get a specific scenario by its name.
+
+.. code-block:: shell
+
+ from testapiclient.client import scenarios
+
+ scenario_client = scenarios.ScenariosClient()
+ scenario_client.get_one('name')
+
+.. NOTE::
+ Response format: { "installers": [], "_id": "", "creation_date": "",
+ "name": "", "creator": ""}
+
+CREATE
+""""""
+
+This method used to create a scenario on the server.
+The user should provide the user parameter and the password
+parameter while initiating the ScenariosClient.
+
+Input for the function :
+
+ * scenario-json : Json object of the scenario
+
+.. NOTE::
+ scenario_json schema - '{ "installers": [],
+ "name": ""}'
+
+ See Installer for installer_schema
+
+.. code-block:: shell
+
+ from testapiclient.client import scenarios
+
+ scenario_client = scenarios.ScenariosClient(user='test', password='pass')
+ scenario_client.create(scenario_json)
+
+UPDATE
+""""""
+
+This method used to update the name of an existing scenario on the server.
+The user should provide the user parameter and the password
+parameter while initiating the ScenariosClient.
+
+Input for the function :
+
+ * scenario-name: name of the scenario which user want to update.
+ * scenario-json: Json object of the scenario
+
+.. NOTE::
+ * scenario_name
+ * scenario_update_json schema - '{"name": ""}'
+
+.. code-block:: shell
+
+ from testapiclient.client import scenarios
+
+ scenario_client = scenarios.ScenariosClient(user='test', password='pass')
+ scenario_client.update(scenario_name, scenario_update_json)
+
+DELETE
+""""""
+
+This method used to delete an existing scenario on the server.
+The user should provide the user parameter and the password
+parameter while initiating the ScenariosClient.
+
+Input for the function :
+
+ * scenario_name: name of the scenario which user want to delete.
+
+.. code-block:: shell
+
+ from testapiclient.client import scenarios
+
+ scenario_client = scenarios.ScenariosClient(user='test', password='pass')
+ scenario_client.delete('scenario_name')
+
+Scenario Installer
+^^^^^^^^^^^^^^^^^^
+
+CREATE
+""""""
+
+This method used to create an installer under a scenario
+on the server. The user should provide the user parameter
+and the password parameter while initiating the InstallersClient.
+
+Input for the function :
+ * scenario_name
+ * installer-json : Json object of the installer
+
+.. NOTE::
+ installer_json schema - '{ "versions": [],
+ "installer": ""}'
+
+ See version for version_schema
+
+.. code-block:: shell
+
+ from testapiclient.client import installers
+
+ installer_client = installers.InstallersClient(user='test', password='pass')
+ installer_client.create(scenario_name, installer_json)
+
+UPDATE
+""""""
+
+This method used to update the all existing installers of a scenario
+The user should provide the user parameter and the password
+parameter while initiating the InstallersClient.
+
+Input for the function :
+
+ * scenario_name
+ * installer-json: Json object of the installer
+
+.. NOTE::
+ * scenario_name
+ * installer_json schema - [{ "versions": [], "installer": ""}]
+
+.. code-block:: shell
+
+ from testapiclient.client import installers
+
+ installer_client = installers.InstallersClient(user='test', password='pass')
+ installer_client.update(scenario_name, installer_update_json)
+
+DELETE
+""""""
+
+This method used to delete existing installers from a scenario.
+on the server.
+The user should provide the user parameter and the password
+parameter while initiating the InstallersClient.
+
+Input for the function :
+ * scenario_name
+ * installer_names: names of the installer which user want to delete.
+
+.. code-block:: shell
+
+ from testapiclient.client import installers
+
+ installer_client = installers.InstallersClient(user='test', password='pass')
+ installer_client.delete(scenario_name, installer_names)
+
+Scenario Version
+^^^^^^^^^^^^^^^^
+
+CREATE
+""""""
+
+This method used to create a version under a scenario
+on the server. The user should provide the user parameter
+and the password parameter while initiating the VersionsClient.
+
+Input for the function :
+
+ * scenario_name
+ * installer_name
+ * version-json : Json object of the version
+
+.. NOTE::
+ version_json schema - '{ "projects": [], "owner": "",
+ "version": ""}'
+
+ See version for version_schema
+
+.. code-block:: shell
+
+ from testapiclient.client import versions
+
+ version_client = versions.VersionsClient(user='test', password='pass')
+ version_client.create(scenario_name, installer_name, version_json)
+
+UPDATE
+""""""
+
+This method used to update the all existing versions of a scenario
+The user should provide the user parameter and the password
+parameter while initiating the VersionsClient.
+
+Input for the function :
+
+ * scenario_name
+ * installer_name
+ * version-json: Json object of the version
+
+.. NOTE::
+ * scenario_name
+ * version_json schema - [{ "projects": [], "owner": "", "version": ""}]
+
+.. code-block:: shell
+
+ from testapiclient.client import versions
+
+ version_client = versions.VersionsClient(user='test', password='pass')
+ version_client.update(scenario_name, installer_name, version_update_json)
+
+DELETE
+""""""
+
+This method used to delete existing versions from a scenario.
+on the server.
+The user should provide the user parameter and the password
+parameter while initiating the VersionsClient.
+
+Input for the function :
+ * scenario_name
+ * installer_name
+ * version_names: names of the version which user want to delete.
+
+.. code-block:: shell
+
+ from testapiclient.client import versions
+
+ version_client = versions.VersionsClient(user='test', password='pass')
+ version_client.delete(scenario_name, installer_name, version_names)
+
+Scenario Project
+^^^^^^^^^^^^^^^^
+
+CREATE
+""""""
+
+This method used to create a project under a scenario
+on the server. The user should provide the user parameter
+and the password parameter while initiating the ProjectsClient.
+
+Input for the function :
+
+ * scenario_name
+ * installer_name
+ * version_name
+ * project-json : Json object of the project
+
+.. NOTE::
+ project_json schema - '{ "scores": [], "trust_indcators": [],
+ "customs": [], "project": ""}'
+
+ See project for project_schema
+
+.. code-block:: shell
+
+ from testapiclient.client import projects
+
+ project_client = projects.ProjectsClient(user='test', password='pass')
+ project_client.create(scenario_name, installer_name, version_name, project_json)
+
+UPDATE
+""""""
+
+This method used to update the all existing projects of a scenario
+The user should provide the user parameter and the password
+parameter while initiating the ProjectsClient.
+
+Input for the function :
+
+ * scenario_name
+ * installer_name
+ * version_name
+ * project-json: Json object of the project
+
+.. NOTE::
+ * scenario_name
+ * project_json schema - [{"scores": [], "trust_indcators": [], "customs": [], "project": ""}]
+
+.. code-block:: shell
+
+ from testapiclient.client import projects
+
+ project_client = projects.ProjectsClient(user='test', password='pass')
+ project_client.update(scenario_name, installer_name, version_name, project_update_json)
+
+DELETE
+""""""
+
+This method used to delete existing projects from a scenario.
+on the server.
+The user should provide the user parameter and the password
+parameter while initiating the ProjectsClient.
+
+Input for the function :
+ * scenario_name
+ * installer_name
+ * version_name
+ * project_names: names of the project which user want to delete.
+
+.. code-block:: shell
+
+ from testapiclient.client import projects
+
+ project_client = projects.ProjectsClient(user='test', password='pass')
+ project_client.delete(scenario_name, installer_name, version_name, project_names)
+
+Scenario Custom
+^^^^^^^^^^^^^^^
+
+CREATE
+""""""
+
+This method used to create a custom under a scenario
+on the server. The user should provide the user parameter
+and the password parameter while initiating the CustomsClient.
+
+Input for the function :
+
+ * scenario_name
+ * installer_name
+ * version_name
+ * project_name
+ * custom : List of Customs
+
+.. NOTE::
+ * scenario_name
+ * custom schema - ["List of Strings"]
+
+ See custom for custom_schema
+
+.. code-block:: shell
+
+ from testapiclient.client import customs
+
+ custom_client = customs.CustomsClient(user='test', password='pass')
+ custom_client.create(scenario_name, installer_name, version_name,
+ project_name, custom_json)
+
+UPDATE
+""""""
+
+This method used to update the all existing customs of a scenario
+The user should provide the user parameter and the password
+parameter while initiating the CustomsClient.
+
+Input for the function :
+
+ * scenario_name
+ * installer_name
+ * version_name
+ * project_name
+ * custom : List of Customs
+
+.. NOTE::
+ * scenario_name
+ * custom schema - ["List of Strings"]
+
+.. code-block:: shell
+
+ from testapiclient.client import customs
+
+ custom_client = customs.CustomsClient(user='test', password='pass')
+ custom_client.update(scenario_name, installer_name, version_name,
+ project_name custom)
+
+DELETE
+""""""
+
+This method used to delete existing customs from a scenario.
+on the server.
+The user should provide the user parameter and the password
+parameter while initiating the CustomsClient.
+
+Input for the function :
+ * scenario_name
+ * installer_name
+ * version_name
+ * project_name
+ * custom: custom which user want to delete.
+
+.. code-block:: shell
+
+ from testapiclient.client import customs
+
+ custom_client = customs.CustomsClient(user='test', password='pass')
+ custom_client.delete(scenario_name, installer_name, version_name,
+ project_name, customs)
+
+Scenario Scores
+^^^^^^^^^^^^^^^
+
+CREATE
+""""""
+
+This method used to create a score under a scenario
+on the server. The user should provide the user parameter
+and the password parameter while initiating the ScoresClient.
+
+Input for the function :
+
+ * scenario_name
+ * installer_name
+ * version_name
+ * project_name
+ * score_json : Schema for the score
+
+.. NOTE::
+ * scenario_name
+ * score_json schema - '{ "date": "", "score": ""}'
+
+ See score for score_schema
+
+.. code-block:: shell
+
+ from testapiclient.client import scores
+
+ score_client = scores.ScoresClient(user='test', password='pass')
+ score_client.create(scenario_name, installer_name, version_name,
+ project_name, score_json)
+
+Scenario TrustIndicator
+^^^^^^^^^^^^^^^^^^^^^^^
+
+CREATE
+""""""
+
+This method used to create a trust indicator under a scenario
+on the server. The user should provide the user parameter
+and the password parameter while initiating the TrustIndicatorsClient.
+
+Input for the function :
+
+ * scenario_name
+ * installer_name
+ * version_name
+ * project_name
+ * trust_indicator_json : Schema for the trust_indicator
+
+.. NOTE::
+ * scenario_name
+ * trust_indicator_json schema - '{ "date": "", "status": ""}'
+
+ See trust_indicator for trust_indicator_schema
+
+.. code-block:: shell
+
+ from testapiclient.client import trust_indicators
+
+ trust_indicator_client = trust_indicators.TrustIndicatorsClient(user='test', password='pass')
+ trust_indicator_client.create(scenario_name, installer_name, version_name,
+ project_name, trust_indicator_json) \ No newline at end of file
diff --git a/testapi/docs/developer/devguide/testapi-client.rst b/testapi/docs/developer/devguide/testapi-client.rst
index ab4c8e8..5ba5df3 100644
--- a/testapi/docs/developer/devguide/testapi-client.rst
+++ b/testapi/docs/developer/devguide/testapi-client.rst
@@ -6,5 +6,859 @@
TestAPI client
==============
-.. toctree::
- :maxdepth: 2
+TestAPIClient is a command-line client for TestAPI that
+brings the command set for pod, project, testcase, results,
+deploy result and scenario together in a single shell with a uniform command
+structure.
+
+
+Installation
+------------
+
+User can install this client from the source.
+
+.. code-block:: shell
+
+ python install testapi/testapi-client/setup.py install
+
+After the installation, user has to set the environment variables
+
+.. code-block:: shell
+
+ source testapi/testapi-client/etc/client.creds
+
+
+Authentication Process
+----------------------
+
+User needs to provide the username and the password with the testapi
+command.
+
+.. code-block:: shell
+
+ $ testapi -u [username] -p [password]
+ (testapi) pod create
+
+
+or
+
+.. code-block:: shell
+
+ testapi pode create -u [username] -p [password] [pod-schema]
+
+First one, user can continue the progress after the authentication.
+cli will create a new session to handle the request.
+
+In second one, cli won't create a session. one time command.
+
+Token is also used for the authorization purpose. User has to obtain the
+valid token from the TestAPI comminity and set it in the following file
+: **testapi/testapi-client/etc/client.creds**
+
+.. code-block:: shell
+
+ source testapi/testapi-client/etc/client.creds
+
+
+Command Structure
+-----------------
+
+TestAPIClient follows a common command Structure.
+
+.. code-block:: shell
+
+ testapi [resource-name] [function] [-u] [username] [-p] [password]
+ [command-arguments]
+
+.. NOTE::
+ resource-name : include first order parent name and resource name.
+
+ example:
+ scenario installer, scenario version, scenario project, scenario custom,
+ scenario trustindicator, scenario score, pod , project, testcase, result,
+ deployresult and scenario.
+
+.. NOTE::
+ -u and -p are optional commands. The user can decide on them.
+
+There are many arguments for each commands. User can get them using
+help command in the cli.
+
+.. code-block:: shell
+
+ pod create --help/-h
+
+Pod
+^^^
+
+Create
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi pod create [-u] [username] [-p] [password] [pod-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) pod create [pod-schema]
+
+.. NOTE::
+ pod-schema - '{"role": "", "name": "", "details": "", "mode": ""}'
+
+Get
+"""
+
+Authentication is not required
+
+.. code-block:: shell
+
+ testapi pod get [-name] [key-word]
+
+.. NOTE::
+ -name is not mandatory. The user can use the -name option to reduce the
+ search result otherwise they will get the details about all pods.
+
+Get one
+"""""""
+
+Authentication is not required
+
+.. code-block:: shell
+
+ testapi pod getone [name-keyword]
+
+.. NOTE::
+ name-keyword is mandatory.
+
+
+Delete
+""""""
+
+Authentication is required
+
+.. code-block:: shell
+
+ testapi pod delete [-u] [username] [-p] [password] [pod-name]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) pod delete [pod-name]
+
+.. NOTE::
+ pod-name is mandatory.
+
+
+Project
+^^^^^^^
+
+Create
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi project create [-u] [username] [-p] [password] [project-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) project create [project-schema]
+
+.. NOTE::
+ project-schema - '{"description": "", "name": ""}'
+
+
+Get
+"""
+
+Authentication is not required
+
+.. code-block:: shell
+
+ testapi project get [-name] [key-word]
+
+.. NOTE::
+ -name is not mandatory. The user can use the -name option to reduce the
+ search result otherwise they will get the details about all projects.
+
+Get one
+"""""""
+
+Authentication is not required
+
+.. code-block:: shell
+
+ testapi project getone [name-keyword]
+
+.. NOTE::
+ name-keyword is mandatory.
+
+Update
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi project put [-u] [username] [-p] [password] [project-name]
+ [project-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) project put [project-name] [project-schema]
+
+.. NOTE::
+ project-schema - '{"name": "", "description": ""}'
+
+Delete
+""""""
+
+Authentication is required
+
+.. code-block:: shell
+
+ testapi project delete [-u] [username] [-p] [password] [project-name]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) project delete [project-name]
+
+.. NOTE::
+ project-name is mandatory.
+
+Testcase
+^^^^^^^^
+
+Create
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi testcase create [-u] [username] [-p] [password]
+ [--project-name] [testcase-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) testcase create [--project-name] [testcase-schema]
+
+.. NOTE::
+ testcase-schema - '{"run": "", "name": "", "ci_loop": "", "tags": "",
+ "url": "", "catalog_description": "", "tier": "",
+ "dependencies": "", "version": "", "criteria": "",
+ "domains": "", "trust": "", "blocking": "",
+ "description": ""}'
+
+
+Get
+"""
+
+Authentication is not required
+
+.. code-block:: shell
+
+ testapi testcase get [--project-name]
+
+.. NOTE::
+ --project-name is mandatory.
+
+Get one
+"""""""
+
+Authentication is not required
+
+.. code-block:: shell
+
+ testapi testcase getone [--project-name] [name]
+
+.. NOTE::
+ name and project-name are mandatory.
+
+Update
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi testcase put [-u] [username] [-p] [password] [--project-name]
+ [name] [testcase-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) testcase put [--project-name] [name] [testcase-schema]
+
+.. NOTE::
+ testcase-schema - '{"run": "", "name": "", "ci_loop": "", "tags": "",
+ "url": "", "catalog_description": "", "tier": "",
+ "dependencies": "", "version": "", "criteria": "",
+ "domains": "", "trust": "", "blocking": "",
+ "description": ""}
+
+
+Result
+^^^^^^^
+
+Create
+""""""
+
+Token is required. Set token as an environment variable.
+
+.. code-block:: shell
+
+ testapi result create [-u] [username] [-p] [password] [result-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) result create [result-schema]
+
+.. NOTE::
+ result-schema - '{"project_name": "", "scenario": "", "stop_date": "",
+ "case_name": "", "build_tag": "", "version": "",
+ "pod_name": "", "criteria": "", "installer": "",
+ "start_date": "", "details": ""}'
+
+
+Get
+"""
+
+Authentication is not required
+
+.. code-block:: shell
+
+ testapi result get [-cli-arguments] [arguments-value]
+
+.. NOTE::
+ List of commandline arguments
+
+ * -case : Search results using tesetcase
+ * -build-tag : Search results using build tag
+ * -from : Search results using from date
+ * -last : Search results using last date
+ * -scenario : Search results using scenario
+ * -period : Search results using period
+ * -project : Search results using project
+ * -to : Search results using to
+ * ---version : Search results using version
+ * -criteria : Search results using criteria
+ * -installer : Search results using installer
+ * -pod : Search results using pod
+ * -page : Search results using page
+
+Get one
+"""""""
+
+Token is required. Set token as an environment variable.
+
+.. code-block:: shell
+
+ testapi result getone [result_id]
+
+.. NOTE::
+ result_id is mandatory.
+
+Deploy Result
+^^^^^^^^^^^^^
+
+Create
+""""""
+
+Token is required. Set token as an environment variable.
+
+
+.. code-block:: shell
+
+ testapi deployresult [-u] [username] [-p] [password]
+ [--project-name] [deployresult-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) deployresult create [deployresult-schema]
+
+.. NOTE::
+ deployresult-schema - '{"run": "", "name": "", "ci_loop": "", "tags": "",
+ "url": "", "catalog_description": "", "tier": "",
+ "dependencies": "", "version": "", "criteria": "",
+ "domains": "", "trust": "", "blocking": "",
+ "description": ""}'
+
+
+Get
+"""
+
+Authentication is not required
+
+.. code-block:: shell
+
+ testapi deployresult get [-cli-arguments] [arguments-value]
+
+.. NOTE::
+ List of command line arguments
+
+ * -job-name : Search results using job
+ * -build-id : Search results using build id
+ * -from : Search results using from date
+ * -last : Search results using last date
+ * -scenario : Search results using scenario
+ * -period : Search results using period
+ * -to : Search results using to
+ * ---version : Search results using version
+ * -criteria : Search results using criteria
+ * -installer : Search results using installer
+ * -pod-name : Search results using pod
+ * -page : Search results using page
+
+Get one
+"""""""
+
+Authentication is not required
+
+.. code-block:: shell
+
+ testapi deployresult getone [deployresult_id]
+
+.. NOTE::
+ deployresult_id is mandatory.
+
+
+Scenario
+^^^^^^^^
+
+Create
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi scenario create [-u] [username] [-p] [password] [scenario-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario create [scenario-schema]
+
+.. NOTE::
+ scenario-schema - '{"name": "", "installers": []}'
+
+
+Get
+"""
+
+Authentication is not required
+
+.. code-block:: shell
+
+ testapi scenario get [-name] [key-word]
+
+.. NOTE::
+
+ user can use some attributes to reduce the search results. These are not
+ mandatory.
+
+ * -name : Backend will use regular expression to search.
+ * -project : Search using project name
+ * -installer : Search using installer name
+ * -version : Search using version name
+
+Get one
+"""""""
+
+Authentication is not required
+
+.. code-block:: shell
+
+ testapi scenario getone [name-keyword]
+
+.. NOTE::
+ name-keyword is mandatory.
+
+Update
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi scenario put [-u] [username] [-p] [password] [scenario-name]
+ [scenario-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario put [scenario-name] [scenario-schema]
+
+.. NOTE::
+ scenario-schema - '{"name": "", "installers": []}'
+
+Delete
+""""""
+
+Authentication is required
+
+.. code-block:: shell
+
+ testapi scenario delete [-u] [username] [-p] [password] [scenario-name]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario delete [scenario-name]
+
+.. NOTE::
+ scenario-name is mandatory.
+
+Scenario installer
+^^^^^^^^^^^^^^^^^^
+
+Create
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi scenario installer create [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] [installer-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario installer create --scenario-name [scenario-name]
+ [installer-schema]
+
+.. NOTE::
+ installer-schema - '{"installer": "", "versions": []}'
+
+Update
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi scenario installer put [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] [installer-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario put --scenario-name [scenario-name] [installer-schema]
+
+.. NOTE::
+ scenario-schema - '{"installer": "", "installers": []}'
+
+Delete
+""""""
+
+Authentication is required
+
+.. code-block:: shell
+
+ testapi scenario delete [-u] [username] [-p] [password] --scenario-name
+ [scenario-name] [name]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario delete --scenario-name [scenario-name] [name]
+
+Scenario version
+^^^^^^^^^^^^^^^^
+
+Create
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi scenario version create [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] --installer [installer] [version-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario installer create --scenario-name [scenario-name]
+ --installer [installer] [version-schema]
+
+.. NOTE::
+ installer-schema - '{"version": "", "owner": "", "projects": []}'
+
+Update
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi scenario installer put [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] --installer [installer] [version-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario installer put --scenario-name [scenario-name]
+ --installer [installer] [installer-schema]
+
+.. NOTE::
+ scenario-schema - '{"version": "","owner": "", "projects": []}'
+
+Delete
+""""""
+
+Authentication is required
+
+.. code-block:: shell
+
+ testapi scenario installer delete [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] --installer [installer] [name]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario installer delete --scenario-name [scenario-name]
+ --installer [installer] [name]
+
+Scenario Project
+^^^^^^^^^^^^^^^^
+
+Create
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi scenario project create [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] --installer [installer]
+ ---version [version] [project-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario project create --scenario-name [scenario-name]
+ --installer [installer] ---version [version] [project-schema]
+
+.. NOTE::
+ installer-schema - '{"scores": [],"customs": [], "trust_indicators": [],
+ project:""}'
+
+Update
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi scenario project put [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] --installer [installer] ---version
+ [version] [project-schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario project put --scenario-name [scenario-name] --installer
+ [installer] ---version [version] [project-schema]
+
+.. NOTE::
+ scenario-schema - '{"scores": [],"customs": [], "trust_indicators": [],
+ project:""}'
+
+Delete
+""""""
+
+Authentication is required
+
+.. code-block:: shell
+
+ testapi scenario project delete [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] --installer [installer] ---version
+ [version] [name]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario project delete --scenario-name [scenario-name]
+ --installer [installer] ---version [version] [name]
+
+Scenario Customs
+^^^^^^^^^^^^^^^^
+
+Create
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi scenario custom create [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] --installer [installer]
+ ---version [version] --project [project] [customs]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario custom create --scenario-name [scenario-name]
+ --installer [installer] ---version [version] --project [project] [customs]
+
+.. NOTE::
+
+ customs : Space sperated strings
+
+Update
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi scenario custom put [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] --installer [installer] ---version
+ [version] --project [project] [customs]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario custom put --scenario-name [scenario-name] --installer
+ [installer] ---version [version] --project [project] [customs]
+
+.. NOTE::
+
+ customs : Space sperated strings
+
+Delete
+""""""
+
+Authentication is required
+
+.. code-block:: shell
+
+ testapi scenario custom delete [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] --installer [installer] ---version
+ [version] --project [project] [customs]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario custom delete --scenario-name [scenario-name]
+ --installer [installer] ---version [version] --project [project]
+ [customs]
+
+.. NOTE::
+
+ customs : Space sperated strings
+
+Scenario Score
+^^^^^^^^^^^^^^
+
+Create
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi scenario score create [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] --installer [installer]
+ ---version [version] --project [project] [score_schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario score create --scenario-name [scenario-name]
+ --installer [installer] ---version [version] --project [project]
+ [score_schema]
+
+.. NOTE::
+
+ score_schema : '{"score": "", "date": ""}'
+
+Scenario TrustIndicators
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Create
+""""""
+
+Authentication required
+
+.. code-block:: shell
+
+ testapi scenario trustindicator create [-u] [username] [-p] [password]
+ --scenario-name [scenario-name] --installer [installer]
+ ---version [version] --project [project] [trustindicator_schema]
+
+or
+
+.. code-block:: shell
+
+ $ testapi [-u] [username] [-p] [password]
+ (testapi) scenario trustindicator create --scenario-name [scenario-name]
+ --installer [installer] ---version [version] --project [project]
+ [trustindicator_schema]
+
+.. NOTE::
+
+ trustindicator_schema : '{"status": "", "date": ""}' \ No newline at end of file
diff --git a/testapi/docs/developer/devguide/web-portal.rst b/testapi/docs/developer/devguide/web-portal.rst
index 62b2f17..8c4bc6c 100644
--- a/testapi/docs/developer/devguide/web-portal.rst
+++ b/testapi/docs/developer/devguide/web-portal.rst
@@ -6,5 +6,115 @@
Web portal
==========
-.. toctree::
- :maxdepth: 2
+**Web-portal of OPNFV Testapi**:
+
+This project aims to provide the web interface for the Testapi framework. It uses the Restful APIs
+of the testapi framework to provide front-end functionalities.
+
+If you are interested in how TestAPI looks like, please visit OPNFV's official `TestAPI Server`__
+
+.. __: http://testresults.opnfv.org/test
+
+Pre-requsites
+=============
+
+In the web portal, we are using AngularJS(1.3.15) as the frontend framework with Bootstrap(v3) CSS.
+
+Running locally
+===============
+
+Installation
+^^^^^^^^^^^^
+
+Web portal will be installed with the testapi framework. No extra installation.
+
+.. code-block:: shell
+
+ python setup.py install
+
+Start Server
+^^^^^^^^^^^^
+
+.. code-block:: shell
+
+ *opnfv-testapi [--config-file <config.ini>]*
+
+If --config-file is provided, the specified configuration file will be employed
+when starting the server, or else /etc/opnfv_testapi/config.ini will be utilized
+by default.
+
+After executing the command successfully, a TestAPI server will be started on
+port 8000, to visit web portal, please access http://hostname:8000
+
+Test
+===============
+
+There are few external requirements for the testing.
+They are
+
+1. npm : node package manager
+ you can get the installation package for nodejs from the official `website`__
+
+ .. __: https://nodejs.org/en/
+
+2. grunt cli : Automation tool
+
+.. code-block:: shell
+
+ npm install -g grunt-cli
+
+After installing global dependencies, you have to install the required local node modules.
+
+.. code-block:: shell
+
+ npm install
+
+**Running tests**
+
+.. code-block:: shell
+
+ grunt e2e
+
+Authentication
+==============
+
+The web portal is using Linux identity server as the Central Authentication Service. The following
+diagram will explain the authentication process.
+
+.. image:: /images/CAS-sequence.jpg
+ :width: 600
+ :alt: Workflow of the Athentication
+
+When a new user initially logs into an application they won't have established a
+session with the application. Instead of displaying a login form asking for the username and
+password, the application (via the CAS Client) will redirect the browser to the linux foundation
+login page. Linux foundation identity server then authenticates the user. If the authentication
+fails, the Linux foundation login page is displayed again with an error message. So until
+authentication succeeds, the user will not be returned to the application.
+
+Authorization
+=============
+
+TestAPI has 3 level authorization layer. They are
+
+**Public**
+
+The public can view the resources(pod, project, testcase, result, deploy result, scenario).
+They do not have the access to create, delete or modify the resources.
+
+**User - Contributors**
+
+Contributors level user can view all the resources(pod, project, testcase, result, deploy result,
+scenario). They can create/delete/modify pod and scenario.
+
+They do not have the access to create project or testcase.
+
+**User - Submitter**
+
+Submitter level user can view all the resources(pod, project, testcase, result, deploy result,
+scenario). They can create/delete/modify pod and scenario.
+
+If user want to create/modify/delete a project or testcase then user has to be in the Submitter
+group for that specific project.
+
+Currently, we can't create/modify/delete results or deploy results from the web portal. \ No newline at end of file
diff --git a/testapi/docs/internship/webportal.rst b/testapi/docs/internship/webportal.rst
new file mode 100644
index 0000000..1ea9c19
--- /dev/null
+++ b/testapi/docs/internship/webportal.rst
@@ -0,0 +1,169 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+
+
+*****************************
+Web Portal for OPNFV Test API
+*****************************
+
+Author: Tharmarajasingam Thuvarakan Mentors: S. Feng, J.Lausuch, M.Richomme
+
+Abstract
+========
+
+TestAPI is used by all the test projects to report results. It is also used to declare projects,
+test cases and labs. It is defined in the Functest developer guide. The internship aims to add web
+portal for TestAPI. The showcase user got through the web portal, will be more human-friendly
+compared to the swagger page. Also, internship aims to build a python client to reduce the workload.
+Python client can be used as a python module.
+
+Overview
+========
+
+The internship time period was from Oct 9th to May 18th. The project proposal page is here [1]_.
+The intern project was assigned to Thuvarakan and was mentored by S. Feng, J.Lausuch, M.Richomme.
+The link to the patches submitted is [2]_. The internship was successfully completed and the
+documentation is as follows.
+
+
+
+Problem Statement
+=================
+
+The following were to be accomplished within the internship time frame.
+
+* Redesign the website theme
+
+ Change the existing theme of the frontend and design a unified theme.
+
+* Add separate pages to each resource
+
+ Create a separate web page for each resource in the new theme.
+
+* Implement all the functionalities in the frontend
+
+ Implement the backend functionalities in the frontend for each
+ resource.
+
+* Authentication for testapiclient
+
+ Implement the authentication functionality in the testapiclient.
+
+* Add all functionalities to testapiclient
+
+ Implement the backend functionalities in the testapiclient for each
+ resource.
+
+* Add support to testapiclient as a python module
+
+ Convert the testapiclient from CLI only to CLI and python module
+ mode.
+
+
+Curation Phase
+==============
+
+The curation phase was the first 4 to 8 weeks of the internship. This phase
+was to get familiar with the testapi code and functionality and propose the
+solutions/tools for the tasks mentioned above.
+
+These are the tools, we proposed for the solutions.
+
+* protractor: An end-to-end test framework for Angular and AngularJS applications
+
+* grunt: A Javascript task runner, a tool used to automatically perform
+ frequent tasks such as minification, compilation, unit testing, and
+ linting.
+
+* cliff: Command Line Interface Formulation Framework.
+
+
+Schedule
+========
+
+=================== ========================================================
+ Date Comment
+=================== ========================================================
+10th Oct ~17th Oct Setting up the development environment, design decisions
+17th Oct ~ 24th Oct Pod web portal CRUD
+24th Oct ~ 31st Oct Projects web portal CRUD
+13st Oct ~ 7th Nov Test cases web portal CRUD
+7th Nov ~ 14th Nov Results web portal R
+14th Nov ~ 21st Nov Results web portal R
+21st Nov ~ 28th Nov Scenario web portal CRUD
+28th Nov ~ 5th Dec Testapi-client framework
+5th Dec ~ 12nd Dec Pods testapi-client CRUD
+12nd Dec ~ 19th Dec Projects testapi-client CRUD
+19th Dec ~ 26th Dec Test cases testapi-client CRUD
+26th Dec ~ 9th Jan Results testapi-client CRUD
+9th Jan ~ 23rd Jan Scenario testapi-client CRUD
+23rd Jan ~ 6th Mar Bugfix in the frontend and testapiclient
+6th Mar ~ 20th Mar Convert testapiclient to python module
+20th Mar ~ 3rd Apr Testing the python module
+3rd Apr ~ 9th May Documentation & Bugfix
+=================== ========================================================
+
+
+FAQ
+===
+
+
+Frontend
+********
+
+1. How to add a new test file for the frontend?
+
+ * Frontend test is handled by protractor [3]_ and
+ automated by the grunt [4]_. All the tests are located in
+ "opnfv_testapi/tests/UI/e2e".
+ First, create a text file in the e2e folder. Then add it to the spec
+ list in the "opnfv_testapi/ui/Gruntfile.js".
+
+
+2. How to test application's functionalities interactively?
+
+ * Application requires authentication for many functionalities.
+ It will cause time for the developer to check the functionalities.
+ Developers can use the application in the authentication false mode.
+ To do that, first, change the authenticate to false in the
+ "etc/config.ini" file then change the authenticate to false in
+ the "opnfv_testapi/ui/config.json" file.
+
+
+3. Browser does not reflect the code changes, what is it mean?
+
+ * Browser is saving the caches for fast reloadings. Sometime browser
+ won't reload the new changes, to solve that we have to clear the browser
+ caches.
+
+
+Testapiclient
+*************
+
+1. How to add a new test file for testapiclient?
+
+ * Frontend test is handled by testtools [5]_ and automated by tox [6]_.
+ All the tests are located in "testapi-client/tests/unit". Create a text
+ file in the unit folder. The name of the test file should start with
+ 'test\_'. It will automatically add that test file to queue.
+
+
+2. Difference between client and cli?
+
+ * Client is used to importing testapiclient as a python module.
+ The cli folder contained the command line interface for the testapiclient.
+
+References
+==========
+
+.. [1] https://wiki.opnfv.org/display/DEV/Intern+Project%3A+Web+Portal+for+OPNFV+Test+API
+
+.. [2] https://gerrit.opnfv.org/gerrit/#/q/status:merged+owner:%22Thuvarakan+Tharmarajasingam+%253Ctharma.thuva%2540gmail.com%253E%22
+
+.. [3] https://www.protractortest.org/
+
+.. [4] https://gruntjs.com
+
+.. [5] https://github.com/testing-cabal/testtools
+
+.. [6] https://tox.readthedocs.io/en/latest/# \ No newline at end of file
diff --git a/testapi/opnfv_testapi/common/check.py b/testapi/opnfv_testapi/common/check.py
index 09a9270..fdc527f 100644
--- a/testapi/opnfv_testapi/common/check.py
+++ b/testapi/opnfv_testapi/common/check.py
@@ -65,12 +65,14 @@ def is_reource_tied(method):
}
if self.table in tied_maps:
if method.__name__ == '_update':
- if 'name' not in self.json_args:
- ret = yield gen.coroutine(method)(self, *args, **kwargs)
- raise gen.Return(ret)
+ if 'name' in self.json_args:
+ if self.json_args['name'] == kwargs.get('query')['name']:
+ ret = yield gen.coroutine(method)(
+ self, *args, **kwargs)
+ raise gen.Return(ret)
query_data[tied_maps[self.table][1]] = kwargs.get('query')['name']
- data = yield dbapi.db_find_one(tied_maps[self.table][0],
- query_data)
+ data = yield dbapi.db_find_one(
+ tied_maps[self.table][0], query_data)
if data:
raises.Unauthorized(message.tied_with_resource())
ret = yield gen.coroutine(method)(self, *args, **kwargs)
diff --git a/testapi/opnfv_testapi/tests/UI/e2e/authenticateFalseSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/authenticateFalseSpec.js
index e287f29..6b9a2bf 100644
--- a/testapi/opnfv_testapi/tests/UI/e2e/authenticateFalseSpec.js
+++ b/testapi/opnfv_testapi/tests/UI/e2e/authenticateFalseSpec.js
@@ -250,7 +250,7 @@ describe('testing the scenarios page for anonymous user', function () {
browser.get(baseURL+"#/scenarios/test-scenario");
var EC = browser.ExpectedConditions;
browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000);
- var buttonAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[2]/button'))
+ var buttonAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[2]/button'))
expect(buttonAdd.isDisplayed()).toBe(true);
});
@@ -258,9 +258,9 @@ describe('testing the scenarios page for anonymous user', function () {
browser.get(baseURL+"#/scenarios/test-scenario");
var EC = browser.ExpectedConditions;
browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000);
- var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[1]/a/p'))
+ var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p'))
installersShow.click();
- var installerDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[1]/td[3]/button'))
+ var installerDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[3]/button'))
expect(installerDelete.isDisplayed()).toBe(true);
});
@@ -268,11 +268,11 @@ describe('testing the scenarios page for anonymous user', function () {
browser.get(baseURL+"#/scenarios/test-scenario");
var EC = browser.ExpectedConditions;
browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000);
- var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[1]/a/p'))
+ var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p'))
installersShow.click();
- var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
installerShow.click();
- var versionAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[2]/button'))
+ var versionAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[2]/button'))
versionAdd.click()
expect(versionAdd.isDisplayed()).toBe(true);
});
@@ -281,15 +281,15 @@ describe('testing the scenarios page for anonymous user', function () {
browser.get(baseURL+"#/scenarios/test-scenario");
var EC = browser.ExpectedConditions;
browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000);
- var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[1]/a/p'))
+ var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p'))
installersShow.click();
- var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
installerShow.click();
- var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p'))
+ var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p'))
versionsShow.click();
- var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
versionShow.click()
- var versionDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody[1]/tr[1]/td[3]/button'))
+ var versionDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody[1]/tr[1]/td[3]/button'))
expect(versionDelete.isDisplayed()).toBe(true);
});
@@ -297,15 +297,15 @@ describe('testing the scenarios page for anonymous user', function () {
browser.get(baseURL+"#/scenarios/test-scenario");
var EC = browser.ExpectedConditions;
browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000);
- var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[1]/a/p'))
+ var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p'))
installersShow.click();
- var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
installerShow.click();
- var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p'))
+ var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p'))
versionsShow.click();
- var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
versionShow.click()
- var projectAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[2]/button'))
+ var projectAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[2]/button'))
projectAdd.click()
expect(projectAdd.isDisplayed()).toBe(true);
});
@@ -314,17 +314,17 @@ describe('testing the scenarios page for anonymous user', function () {
browser.get(baseURL+"#/scenarios/test-scenario");
var EC = browser.ExpectedConditions;
browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000);
- var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[1]/a/p'))
+ var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p'))
installersShow.click();
- var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
installerShow.click();
- var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p'))
+ var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p'))
versionsShow.click();
- var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
versionShow.click()
- var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a'))
+ var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a'))
projectsShow.click();
- var projectDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[1]/td[3]/button'))
+ var projectDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[1]/td[3]/button'))
projectDelete.click()
expect(projectDelete.isDisplayed()).toBe(true);
});
@@ -333,24 +333,24 @@ describe('testing the scenarios page for anonymous user', function () {
browser.get(baseURL+"#/scenarios/test-scenario");
var EC = browser.ExpectedConditions;
browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000);
- var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[1]/a/p'))
+ var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p'))
installersShow.click();
- var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
installerShow.click();
- var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p'))
+ var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p'))
versionsShow.click();
- var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
versionShow.click()
- var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a'))
+ var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a'))
projectsShow.click();
- var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
projectShow.click();
- var customsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/a/p'))
+ var customsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/a/p'))
customsShow.click();
var row = element.all(by.repeater('(indexCU, custom) in project.customs')).first();
var cells = row.all(by.tagName('td'));
expect(cells.get(0).getText()).toContain("dvs");
- var buttonAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/button'))
+ var buttonAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/button'))
buttonAdd.click()
expect(buttonAdd.isDisplayed()).toBe(true);
});
@@ -359,24 +359,24 @@ describe('testing the scenarios page for anonymous user', function () {
browser.get(baseURL+"#/scenarios/test-scenario");
var EC = browser.ExpectedConditions;
browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000);
- var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[1]/a/p'))
+ var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p'))
installersShow.click();
- var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
installerShow.click();
- var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p'))
+ var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p'))
versionsShow.click();
- var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
versionShow.click()
- var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a'))
+ var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a'))
projectsShow.click();
- var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
+ var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a'))
projectShow.click();
- var customsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/a/p'))
+ var customsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/a/p'))
customsShow.click();
var row = element.all(by.repeater('(indexCU, custom) in project.customs')).first();
var cells = row.all(by.tagName('td'));
expect(cells.get(0).getText()).toContain("dvs");
- var buttonDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[4]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/table/tbody/tr[1]/td[2]/button'))
+ var buttonDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/table/tbody/tr[1]/td[2]/button'))
buttonDelete.click()
expect(buttonDelete.isDisplayed()).toBe(true);
});
diff --git a/testapi/opnfv_testapi/tests/UI/e2e/deployResultsControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/deployResultsControllerSpec.js
index e00243b..40f60e4 100644
--- a/testapi/opnfv_testapi/tests/UI/e2e/deployResultsControllerSpec.js
+++ b/testapi/opnfv_testapi/tests/UI/e2e/deployResultsControllerSpec.js
@@ -383,7 +383,7 @@ describe('testing the result page for user', function () {
buttonClear.click();
var row = element.all(by.repeater('(index, result) in ctrl.data.deployresults')).first();
var cells = row.all(by.tagName('td'));
- expect(cells.get(0).getText()).toContain("3c9f8d62");
+ expect(cells.get(0).getText()).toContain("3c9f8d63");
});
it('view the deploy results ', function () {
diff --git a/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js
index 16b219d..ac1f954 100644
--- a/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js
+++ b/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js
@@ -78,7 +78,7 @@ describe('testing the Pods page for anonymous user', function () {
it('Sort the results by mode', function () {
browser.get(baseURL+'#/pods');
- var sortMode = element(by.xpath('//*[@id="ng-app"]/body/div/div[6]/div/table/thead/tr/th[4]/a[2]/span'))
+ var sortMode = element(by.xpath('//*[@id="ng-app"]/body/div/div[5]/div/table/thead/tr/th[4]/a[2]/span'))
sortMode.click();
var row = element.all(by.repeater('(index, pod) in ctrl.data.pods')).first();
var cells = row.all(by.tagName('td'));
@@ -87,7 +87,7 @@ describe('testing the Pods page for anonymous user', function () {
it('Sort the results by role', function () {
browser.get(baseURL+'#/pods');
- var sortRole = element(by.xpath('//*[@id="ng-app"]/body/div/div[6]/div/table/thead/tr/th[3]/a[2]/span'))
+ var sortRole = element(by.xpath('//*[@id="ng-app"]/body/div/div[5]/div/table/thead/tr/th[3]/a[2]/span'))
sortRole.click();
var row = element.all(by.repeater('(index, pod) in ctrl.data.pods')).first();
var cells = row.all(by.tagName('td'));
@@ -262,8 +262,11 @@ describe('testing the Pods page for authorized user', function () {
.isDisplayed()).toBe(true);
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Delete Success"))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Delete Success"))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('Delete the pods ', function () {
@@ -272,8 +275,11 @@ describe('testing the Pods page for authorized user', function () {
deleteOperation.click();
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Delete Success"))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Delete Success"))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('Create the pod', function () {
@@ -286,8 +292,11 @@ describe('testing the Pods page for authorized user', function () {
name.sendKeys('test1');
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Create Success"))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Create Success"))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('Showing error when creating with a empty name ', function () {
@@ -299,8 +308,11 @@ describe('testing the Pods page for authorized user', function () {
browser.wait(EC.visibilityOf(name), 5000);
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click()
- expect(element(by.cssContainingText(".alert","Name is missing."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".error.show","Name is missing."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('cancel the delete confimation modal of the pod ', function () {
@@ -356,8 +368,11 @@ describe('testing the Pods page for authorized user', function () {
deleteOperation.click();
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.css(".alert.alert-danger"))
+ browser.ignoreSynchronization = true;
+ expect(element(by.css(".error.show"))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('view the test case ', function () {
@@ -394,8 +409,13 @@ describe('testing the Pods page for authorized user', function () {
},
]);
browser.get(baseURL+"#/pods");
- expect(element(by.css(".alert.alert-danger"))
+ var EC = browser.ExpectedConditions;
+ browser.wait(EC.urlContains(baseURL+ '/#/pods'), 5000);
+ browser.ignoreSynchronization = true;
+ expect(element(by.css(".error.show"))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
}); \ No newline at end of file
diff --git a/testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js
index 1117ef5..da86389 100644
--- a/testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js
+++ b/testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js
@@ -324,8 +324,12 @@ describe('testing the Project Link for user who is in submitter group', function
name.sendKeys('testproject');
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Project is successfully created."))
+
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Project is successfully created."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('Show error if user doesnt have permission to Create the Project', function () {
@@ -340,7 +344,10 @@ describe('testing the Project Link for user who is in submitter group', function
description.sendKeys('demoDescription');
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.css(".alert.alert-danger")).isDisplayed()).toBe(true);
+ browser.ignoreSynchronization = true;
+ expect(element(by.css(".error")).isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('Showing error when creating with a empty name ', function () {
@@ -352,8 +359,11 @@ describe('testing the Project Link for user who is in submitter group', function
browser.wait(EC.visibilityOf(name), 5000);
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
+ browser.ignoreSynchronization = true;
expect(element(by.cssContainingText(".alert","Name is missing."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('Show error when user click the create button with an already existing name', function () {
@@ -368,7 +378,10 @@ describe('testing the Project Link for user who is in submitter group', function
description.sendKeys('demoDescription');
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.css(".alert.alert-danger")).isDisplayed()).toBe(true);
+ browser.ignoreSynchronization = true;
+ expect(element(by.css(".error")).isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('cancel the delete confimation modal of the project ', function () {
@@ -388,8 +401,11 @@ describe('testing the Project Link for user who is in submitter group', function
.isDisplayed()).toBe(true);
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Projects is successfully deleted"))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Projects is successfully deleted"))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it(' Show error if user doesnt has permission to delete the projects ', function () {
@@ -442,7 +458,10 @@ describe('testing the Project Link for user who is in submitter group', function
deleteOperation.click();
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.css(".alert.alert-danger")).isDisplayed()).toBe(true);
+ browser.ignoreSynchronization = true;
+ expect(element(by.css(".error")).isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('cancel the Edit modal of the Project ', function () {
@@ -468,8 +487,12 @@ describe('testing the Project Link for user who is in submitter group', function
name.sendKeys('test1');
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click()
- expect(element(by.cssContainingText(".alert","Project is successfully updated."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Project is successfully updated."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
+
});
it('Show error if user doesnt has permission to edit the projects ', function () {
@@ -526,7 +549,10 @@ describe('testing the Project Link for user who is in submitter group', function
name.sendKeys('test1');
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click()
- expect(element(by.css(".alert.alert-danger")).isDisplayed()).toBe(true);
+ browser.ignoreSynchronization = true;
+ expect(element(by.css(".error")).isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('Batch Delete the projects ', function () {
@@ -537,8 +563,12 @@ describe('testing the Project Link for user who is in submitter group', function
buttonDelete.click();
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Projects is successfully deleted"))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Projects is successfully deleted"))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
+
});
it('If backend is not responding then show error when user click the create button',function(){
@@ -570,8 +600,10 @@ describe('testing the Project Link for user who is in submitter group', function
name.sendKeys('testproject');
details.sendKeys('demoDescription');
var buttonOK = element(by.buttonText('Ok'));
- buttonOK.click().then(function(){
- expect(element(by.css(".alert.alert-danger")).isDisplayed()).toBe(true);
- });
+ buttonOK.click()
+ browser.ignoreSynchronization = true;
+ expect(element(by.css(".error")).isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
})
diff --git a/testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js
index 925e82c..48690a1 100644
--- a/testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js
+++ b/testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js
@@ -198,8 +198,8 @@ describe('testing the result page for anonymous user', function () {
browser.wait(EC.urlContains(baseURL+ '#/results'), 10000);
var resultLink = element(by.linkText('0e2643f4')).click();
browser.wait(EC.urlContains(baseURL+ '#/result/5a45170bbb2092000e2643f4'), 10000);
- expect(element(by.cssContainingText(".key.col-md-1","failures")).isDisplayed()).toBe(true);
- expect(element(by.cssContainingText(".leaf-value.col-md-11","0")).isDisplayed()).toBe(true);
+ expect(element(by.cssContainingText(".key.col-md-2","failures")).isDisplayed()).toBe(true);
+ expect(element(by.cssContainingText(".leaf-value.col-md-10","0")).isDisplayed()).toBe(true);
});
it('Should show the results in results page related to the filters', function () {
diff --git a/testapi/opnfv_testapi/tests/UI/e2e/scenarioControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/scenarioControllerSpec.js
index 7777721..37b42dc 100644
--- a/testapi/opnfv_testapi/tests/UI/e2e/scenarioControllerSpec.js
+++ b/testapi/opnfv_testapi/tests/UI/e2e/scenarioControllerSpec.js
@@ -682,8 +682,11 @@ describe('testing the scenarios page for user', function () {
name.sendKeys('test');
var buttonOk = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[2]/button[1]'))
buttonOk.click()
- expect(element(by.cssContainingText(".alert","Installers are successfully updated."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Installers are successfully updated."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
@@ -720,8 +723,11 @@ describe('testing the scenarios page for user', function () {
.isDisplayed()).toBe(true);
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Installer is successfully deleted."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Installer is successfully deleted."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it( 'Expand installer by user', function() {
@@ -753,8 +759,11 @@ describe('testing the scenarios page for user', function () {
owner.sendKeys('testOwner');
var buttonOk = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[2]/button[1]'))
buttonOk.click()
- expect(element(by.cssContainingText(".alert","Versions are successfully updated."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Versions are successfully updated."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it( 'Expand versions by user', function() {
@@ -793,8 +802,11 @@ describe('testing the scenarios page for user', function () {
.isDisplayed()).toBe(true);
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Versions are successfully deleted."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Versions are successfully deleted."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it( 'Expand version by user', function() {
@@ -832,8 +844,11 @@ describe('testing the scenarios page for user', function () {
project.sendKeys('testP');
var buttonOk = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[2]/button[1]'))
buttonOk.click()
- expect(element(by.cssContainingText(".alert","Projects are successfully updated."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Projects are successfully updated."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it( 'Expand projects by user', function() {
@@ -878,8 +893,11 @@ describe('testing the scenarios page for user', function () {
.isDisplayed()).toBe(true);
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Projects are successfully Deleted."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Projects are successfully Deleted."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it( 'Expand project by user', function() {
@@ -1011,8 +1029,11 @@ describe('testing the scenarios page for user', function () {
custom.sendKeys('testC');
var buttonOk = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[2]/button[1]'))
buttonOk.click()
- expect(element(by.cssContainingText(".alert","Customs are successfully updated."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Customs are successfully updated."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it( 'Add multiple Customs by user', function() {
@@ -1043,8 +1064,11 @@ describe('testing the scenarios page for user', function () {
custom.sendKeys('testC,testD,');
var buttonOk = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[2]/button[1]'))
buttonOk.click()
- expect(element(by.cssContainingText(".alert","Customs are successfully updated."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Customs are successfully updated."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it( 'Delete Customs by user', function() {
@@ -1074,8 +1098,11 @@ describe('testing the scenarios page for user', function () {
.isDisplayed()).toBe(true);
var buttonOk = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div[3]/button[1]'))
buttonOk.click()
- expect(element(by.cssContainingText(".alert","Customs are successfully deleted."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Customs are successfully deleted."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
}); \ No newline at end of file
diff --git a/testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js
index e7c5fb0..55922ad 100644
--- a/testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js
+++ b/testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js
@@ -119,7 +119,7 @@ describe('testing the scenarios page for anonymous user', function () {
it('Sort scenarios', function () {
browser.get(baseURL+"#/scenarios");
- var sort = element(by.xpath('//*[@id="ng-app"]/body/div/div[4]/div/table/thead/tr/th[2]/a[2]/span'))
+ var sort = element(by.xpath('//*[@id="ng-app"]/body/div/div[5]/div/table/thead/tr/th[2]/a[2]/span'))
sort.click();
var row = element.all(by.repeater('(index, scenario) in ctrl.data.scenarios')).first();
var cells = row.all(by.tagName('td'));
@@ -284,8 +284,11 @@ describe('testing the scenarios page for user', function () {
name.sendKeys('test');
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Scenario is successfully created."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Scenario is successfully created."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('create scenarrio by user with installers ', function () {
@@ -304,8 +307,11 @@ describe('testing the scenarios page for user', function () {
buttonOK.click();
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Scenario is successfully created."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Scenario is successfully created."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('create scenarrio by user with installers with versions ', function () {
@@ -333,8 +339,11 @@ describe('testing the scenarios page for user', function () {
buttonOK.click();
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Scenario is successfully created."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Scenario is successfully created."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('create scenarrio by user with installers with versions with project', function () {
@@ -369,8 +378,11 @@ describe('testing the scenarios page for user', function () {
buttonOK.click();
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Scenario is successfully created."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Scenario is successfully created."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('create scenarrio by user with installers with versions with project with custom', function () {
@@ -412,8 +424,11 @@ describe('testing the scenarios page for user', function () {
buttonOK.click();
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Scenario is successfully created."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Scenario is successfully created."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('view scenarrio by user ', function () {
@@ -443,8 +458,11 @@ describe('testing the scenarios page for user', function () {
.isDisplayed()).toBe(true);
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Scenario is successfully deleted."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Scenario is successfully deleted."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('Batch Delete the scenarios ', function () {
@@ -455,8 +473,11 @@ describe('testing the scenarios page for user', function () {
buttonDelete.click();
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Scenario is successfully deleted."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Scenario is successfully deleted."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('Edit the scenarios ', function () {
@@ -469,8 +490,11 @@ describe('testing the scenarios page for user', function () {
name.sendKeys('test2');
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click()
- expect(element(by.cssContainingText(".alert","Scenario is successfully Updated."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Scenario is successfully Updated."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
}); \ No newline at end of file
diff --git a/testapi/opnfv_testapi/tests/UI/e2e/testCasesControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/testCasesControllerSpec.js
index 53e7bdf..38e0f24 100644
--- a/testapi/opnfv_testapi/tests/UI/e2e/testCasesControllerSpec.js
+++ b/testapi/opnfv_testapi/tests/UI/e2e/testCasesControllerSpec.js
@@ -550,8 +550,11 @@ describe('testing the test cases page for user who is in submitter group', funct
name.sendKeys('test');
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Testcase is successfully created."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Testcase is successfully created."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('Showing error when creating with a empty name ', function () {
@@ -565,8 +568,11 @@ describe('testing the test cases page for user who is in submitter group', funct
browser.wait(EC.visibilityOf(name), 5000);
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Name is missing."))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".error.show","Name is missing."))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('cancel the delete confimation modal of the test case ', function () {
@@ -590,8 +596,11 @@ describe('testing the test cases page for user who is in submitter group', funct
deleteOperation.click();
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Test case is successfully deleted"))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Test case is successfully deleted"))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('cancel the Edit modal of the test case ', function () {
@@ -621,8 +630,11 @@ describe('testing the test cases page for user who is in submitter group', funct
name.sendKeys('test1');
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Test case is successfully updated"))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Test case is successfully updated"))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
it('view the test case ', function () {
@@ -646,7 +658,10 @@ describe('testing the test cases page for user who is in submitter group', funct
buttonDelete.click();
var buttonOK = element(by.buttonText('Ok'));
buttonOK.click();
- expect(element(by.cssContainingText(".alert","Test case is successfully deleted"))
+ browser.ignoreSynchronization = true;
+ expect(element(by.cssContainingText(".success.show","Test case is successfully deleted"))
.isDisplayed()).toBe(true);
+ browser.sleep(500);
+ browser.ignoreSynchronization = false;
});
})
diff --git a/testapi/opnfv_testapi/ui/Gruntfile.js b/testapi/opnfv_testapi/ui/Gruntfile.js
index 805ad9f..ab59475 100644
--- a/testapi/opnfv_testapi/ui/Gruntfile.js
+++ b/testapi/opnfv_testapi/ui/Gruntfile.js
@@ -6,7 +6,22 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-wait');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-connect');
+ grunt.loadNpmTasks('grunt-convert');
grunt.initConfig({
+ convert: {
+ options: {
+ explicitArray: false,
+ },
+ json2xml: {
+ options: {
+ xml: {
+ header: true
+ }
+ },
+ src: ['../tests/UI/coverage/coverage.json'],
+ dest: '../tests/UI/coverage/coverage.xml'
+ }
+ },
connect: {
server: {
options: {
@@ -159,6 +174,7 @@ module.exports = function (grunt) {
'wait:default',
'protractor_coverage',
'makeReport',
+ 'convert',
'shell:deleteFiles'
]);
}
diff --git a/testapi/opnfv_testapi/ui/components/pods/pods.html b/testapi/opnfv_testapi/ui/components/pods/pods.html
index 8e66a9c..b5dadf5 100644
--- a/testapi/opnfv_testapi/ui/components/pods/pods.html
+++ b/testapi/opnfv_testapi/ui/components/pods/pods.html
@@ -19,22 +19,18 @@
<div class="col-sm-1 pull-right">
<button type="button" class="btn btn-success" ng-click="ctrl.listPods()">
<i class="fa fa-search"></i> Filter</button>
+ <div ng-class="{'show': ctrl.showError}" id="toast" class="error">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true" ></span>
+ {{ctrl.error}}</div>
+ <div ng-class="{'show': ctrl.showSuccess}" id="toast" class="success">
+ <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
+ {{ctrl.success}}</div>
</div>
<div class="col-sm-3 pull-right">
<span style="margin-top:6px">Search:&nbsp;&nbsp;</span>
<input type="text" class="form-control search" ng-enter="ctrl.listPods()" ng-Model="ctrl.filterText" placeholder="Search String">
</div>
</div>
-<div class="col-md-12">
- <div ng-show="ctrl.showError" class="col-md-12 alert alert-danger" role="alert">
- <span class="pull-right">&nbsp;{{ctrl.error}}</span>
- <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
- </div>
- <div ng-show="ctrl.showSuccess" class="col-md-12 alert alert-success" role="alert">
- <span class="pull-right">&nbsp;{{ctrl.success}}</span>
- <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span>
- </div>
-</div>
<div class="col-md-12" style="padding-right:0px">
<div class="table-responsive">
<table class="table table-bordered table-hover" ng-data="ctrl.data.pods">
diff --git a/testapi/opnfv_testapi/ui/components/pods/podsController.js b/testapi/opnfv_testapi/ui/components/pods/podsController.js
index c50fa5a..3b6ab97 100644
--- a/testapi/opnfv_testapi/ui/components/pods/podsController.js
+++ b/testapi/opnfv_testapi/ui/components/pods/podsController.js
@@ -21,7 +21,7 @@
PodsController.$inject = [
'$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert',
- 'confirmModal', 'keepState', 'sortService'
+ 'confirmModal', 'keepState', 'sortService', '$timeout'
];
/**
@@ -30,7 +30,7 @@
* through pods declared in TestAPI.
*/
function PodsController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl,
- raiseAlert, confirmModal, keepState, sortService) {
+ raiseAlert, confirmModal, keepState, sortService, $timeout) {
var ctrl = this;
ctrl.url = testapiApiUrl + '/pods';
ctrl.checkBox = []
@@ -48,6 +48,18 @@
ctrl.batchDelete = batchDelete;
ctrl.viewPod = viewPod
ctrl.sortBy = sortBy
+ ctrl.toastError = toastError
+ ctrl.toastSuccess = toastSuccess
+
+ function toastError() {
+ ctrl.showError = true
+ $timeout(function(){ ctrl.showError = false;}, 3000);
+ }
+
+ function toastSuccess() {
+ ctrl.showSuccess = true
+ $timeout(function(){ ctrl.showSuccess = false;}, 3000);
+ }
function sortBy(field){
ctrl.data.pods = sortService.sortFunction(ctrl.data.pods, field , ctrl.sorting[field] )
@@ -82,19 +94,21 @@
role: pod.role,
details: pod.details
};
- ctrl.podsRequest =
- $http.post(pods_url, body).success(function (data) {
- ctrl.showSuccess = true ;
+ ctrl.podsRequest = $http.post(pods_url, body)
+
+ ctrl.podsRequest.success(function (data) {
ctrl.success = "Create Success"
+ ctrl.toastSuccess()
ctrl.listPods();
}).catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError()
});
+ return ctrl.podsRequest
}
else{
- ctrl.showError = true;
ctrl.error = 'Name is missing.'
+ ctrl.toastError()
}
}
@@ -124,8 +138,8 @@
}
}).catch(function (data) {
ctrl.data = null;
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError()
});
}
@@ -139,12 +153,12 @@
function podDelete(podName){
var pods_url = ctrl.url + "/" + podName
$http.delete(pods_url).success(function(){
- ctrl.showSuccess = true ;
ctrl.success = "Delete Success"
+ ctrl.toastSuccess()
ctrl.listPods();
}).catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError()
});
}
@@ -247,9 +261,10 @@
* inputs.
*/
function confirm() {
- $uibModalInstance.close();
if (angular.isDefined(ctrl.data.successHandler)) {
- ctrl.data.successHandler(ctrl.pod);
+ ctrl.data.successHandler(ctrl.pod).success( function(data){
+ $uibModalInstance.close();
+ })
}
}
diff --git a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html
index 395db03..04baa9c 100644
--- a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html
+++ b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html
@@ -11,16 +11,12 @@
<i class="fa fa-plus"></i> Create</button>
</div>
</div>
- <div class='clo-md-12'>
- <div ng-show="testCasesCtrl.showError" class="alert alert-danger" role="alert">
- <span class="pull-right">&nbsp;{{testCasesCtrl.error}}</span>
- <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
- </div>
- <div ng-show="testCasesCtrl.showSuccess" class="alert alert-success" role="alert">
- <span class="pull-right">&nbsp;{{testCasesCtrl.successMessage}}</span>
- <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span>
- </div>
- </div>
+ <div ng-class="{'show': testCasesCtrl.showError}" id="toast" class="error">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true" ></span>
+ {{testCasesCtrl.error}}</div>
+ <div ng-class="{'show': testCasesCtrl.showSuccess}" id="toast" class="success">
+ <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
+ {{testCasesCtrl.success}}</div>
<div class='clo-md-12' style="padding-right:0px">
<div class="table-responsive">
<table class="table table-bordered table-hover" ng-data="testCasesCtrl.data.testcases">
diff --git a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js
index 4d6153e..ea0498a 100644
--- a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js
+++ b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js
@@ -21,7 +21,7 @@
TestCasesController.$inject = [
'$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert',
- 'confirmModal', 'authenticate'
+ 'confirmModal', 'authenticate', '$timeout'
];
/**
@@ -31,7 +31,7 @@
* in them.
*/
function TestCasesController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl,
- raiseAlert, confirmModal, authenticate) {
+ raiseAlert, confirmModal, authenticate, $timeout) {
var ctrl = this;
ctrl.loadDetails = loadDetails;
ctrl.name = $state.params['name'];
@@ -49,29 +49,40 @@
ctrl.checkBox = [];
ctrl.checkBoxList = [];
+ ctrl.toastError = toastError
+ ctrl.toastSuccess = toastSuccess
+
+ function toastError() {
+ ctrl.showError = true
+ $timeout(function(){ ctrl.showError = false;}, 3000);
+ }
+
+ function toastSuccess() {
+ ctrl.showSuccess = true
+ $timeout(function(){ ctrl.showSuccess = false;}, 3000);
+ }
/**
* This will contact the TestAPI to create a new test case.
*/
function createTestCase(name, testcase) {
- ctrl.showError = false;
- ctrl.showSuccess = false;
if(testcase.name != "" && testcase.name!=null){
var testCase_url = ctrl.requestUrl;
- ctrl.testCasesRequest =
- $http.post(testCase_url, testcase).success(function (data){
- ctrl.showSuccess = true ;
- ctrl.successMessage = "Testcase is successfully created."
+ ctrl.testCasesRequest = $http.post(testCase_url, testcase)
+ ctrl.testCasesRequest.success(function (data){
+ ctrl.success = "Testcase is successfully created."
loadDetails();
+ ctrl.toastSuccess()
})
.catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
+ return ctrl.testCasesRequest;
}
else{
- ctrl.showError = true;
ctrl.error = 'Name is missing.'
+ ctrl.toastError();
}
}
@@ -114,24 +125,23 @@
* This will contact the TestAPI to update an existing test case.
*/
function updateTestCase(name, testCase) {
- ctrl.showError = false;
- ctrl.showSuccess = false;
if(testCase.name != ""){
var testCase_url = ctrl.requestUrl + '/' + name;
- ctrl.testCasesRequest =
- $http.put(testCase_url, testCase).success(function (data){
- ctrl.showSuccess = true ;
- ctrl.successMessage = "Test case is successfully updated"
+ ctrl.testCasesRequest = $http.put(testCase_url, testCase)
+ ctrl.testCasesRequest.success(function (data){
+ ctrl.success = "Test case is successfully updated"
loadDetails();
+ ctrl.toastSuccess();
})
.catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError()
});
+ return ctrl.testCasesRequest;
}
else{
- ctrl.showError = true;
ctrl.error = 'Name is missing.'
+ ctrl.toastError()
}
}
@@ -139,16 +149,14 @@
* This will contact the TestAPI to delete an existing test case.
*/
function deleteTestCase(name) {
- ctrl.showError = false;
- ctrl.showSuccess = false;
ctrl.testCasesRequest =
$http.delete(ctrl.requestUrl+"/"+name).success(function (data) {
loadDetails();
- ctrl.showSuccess = true ;
- ctrl.successMessage = "Test case is successfully deleted"
+ ctrl.success = "Test case is successfully deleted";
+ ctrl.toastSuccess();
}).catch(function (error) {
- ctrl.showError = true;
- ctrl.error = data.statusText;
+ ctrl.error = error.statusText;
+ ctrl.toastError();
});
}
@@ -218,8 +226,8 @@
ctrl.data = data;
}).catch(function (error) {
ctrl.data = null;
- ctrl.showError = true;
ctrl.error = error.statusText;
+ ctrl.toastError()
});
}
ctrl.loadDetails();
@@ -271,9 +279,15 @@
* inputs.
*/
function confirm() {
- $uibModalInstance.close();
if (angular.isDefined(ctrl.data.successHandler)) {
- ctrl.data.successHandler(ctrl.name, ctrl.testcase);
+ if(ctrl.testcase.name){
+ ctrl.data.successHandler(ctrl.name, ctrl.testcase).success( function(){
+ $uibModalInstance.close();
+ })
+ }
+ else{
+ ctrl.data.successHandler(ctrl.name, ctrl.testcase)
+ }
}
}
diff --git a/testapi/opnfv_testapi/ui/components/projects/projects.html b/testapi/opnfv_testapi/ui/components/projects/projects.html
index 5d514d1..3098aa2 100644
--- a/testapi/opnfv_testapi/ui/components/projects/projects.html
+++ b/testapi/opnfv_testapi/ui/components/projects/projects.html
@@ -21,16 +21,12 @@
<input type="text" class="form-control search" ng-enter="ctrl.listProjects()" ng-Model="ctrl.filterText" style="width:80%;" placeholder="Search By Name">
</div>
</div>
-<div class='clo-md-12'>
- <div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
- <span class="pull-right">&nbsp;{{ctrl.error}}</span>
- <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
- </div>
- <div ng-show="ctrl.showSuccess" class="alert alert-success" role="alert">
- <span class="pull-right">&nbsp;{{ctrl.success}}</span>
- <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span>
- </div>
-</div>
+<div ng-class="{'show': ctrl.showError}" id="toast" class="error">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true" ></span>
+ {{ctrl.error}}</div>
+<div ng-class="{'show': ctrl.showSuccess}" id="toast" class="success">
+ <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
+ {{ctrl.success}}</div>
<div class='clo-md-12' style="padding-right:0px">
<div class="table-responsive">
<table class="table table-bordered table-hover" ng-data="ctrl.data.projects">
diff --git a/testapi/opnfv_testapi/ui/components/projects/projectsController.js b/testapi/opnfv_testapi/ui/components/projects/projectsController.js
index 4f0af0f..42100bd 100644
--- a/testapi/opnfv_testapi/ui/components/projects/projectsController.js
+++ b/testapi/opnfv_testapi/ui/components/projects/projectsController.js
@@ -21,7 +21,7 @@
ProjectsController.$inject = [
'$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl',
- 'raiseAlert', 'confirmModal', 'authenticate', 'keepState', 'sortService'
+ 'raiseAlert', 'confirmModal', 'authenticate', 'keepState', 'sortService', '$timeout'
];
/**
@@ -30,7 +30,7 @@
* through projects declared in TestAPI.
*/
function ProjectsController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl,
- raiseAlert, confirmModal, authenticate, keepState, sortService) {
+ raiseAlert, confirmModal, authenticate, keepState, sortService, $timeout) {
var ctrl = this;
ctrl.url = testapiApiUrl + '/projects';
@@ -51,27 +51,41 @@
ctrl.name = '';
ctrl.details = '';
ctrl.ascending = false;
+ ctrl.toastError = toastError
+ ctrl.toastSuccess = toastSuccess
+
+ function toastError() {
+ ctrl.showError = true
+ $timeout(function(){ ctrl.showError = false;}, 7000);
+ }
+
+ function toastSuccess() {
+ ctrl.showSuccess = true
+ $timeout(function(){ ctrl.showSuccess = false;}, 7000);
+ }
/**
* This will contact the TestAPI to create a new project.
*/
function create(project) {
- ctrl.showError = false;
- ctrl.showSuccess = false;
var projects_url = ctrl.url;
var body = {
name: project.name,
description: project.description
};
- ctrl.projectsRequest =
- $http.post(projects_url, body).success(function (data){
- ctrl.showSuccess = true ;
- ctrl.success = "Project is successfully created."
+ ctrl.projectsRequest = $http.post(projects_url, body)
+ ctrl.projectsRequest.success(function (data){
+ ctrl.success = "Project is successfully created.";
ctrl.listProjects();
+ ctrl.toastSuccess();
+ ctrl.request = true;
}).catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
+ ctrl.request = false;
});
+
+ return ctrl.projectsRequest
}
function sortByName(){
@@ -135,16 +149,17 @@
ctrl.showError = false;
ctrl.showSuccess = false;
var projectUrl = ctrl.url + '/' + name;
- ctrl.testCasesRequest =
- $http.put(projectUrl, project).success(function (data){
- ctrl.showSuccess = true ;
+ ctrl.projectRequest = $http.put(projectUrl, project)
+ ctrl.projectRequest.success(function (data){
ctrl.success = "Project is successfully updated."
- listProjects();
+ ctrl.listProjects();
+ ctrl.toastSuccess();
})
.catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
+ return ctrl.projectRequest
}
/**
@@ -174,8 +189,8 @@
}
}).catch(function (data) {
ctrl.data = null;
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
}
@@ -190,13 +205,12 @@
function projectDelete(projectName){
var projectUrl = ctrl.url + "/" + projectName
$http.delete(projectUrl).success(function(){
- ctrl.showSuccess = true ;
ctrl.success = "Projects is successfully deleted"
+ ctrl.toastSuccess();
ctrl.listProjects();
}).catch(function (data) {
- ctrl.showError = true;
- ctrl.showSuccess = false;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
}
@@ -277,11 +291,15 @@
function confirm() {
if (angular.isDefined(ctrl.data.successHandler)) {
if(ctrl.project.name != ""){
- $uibModalInstance.close();
+ var success = false;
if(ctrl.data.project){
- ctrl.data.successHandler(ctrl.projectName, ctrl.project);
+ ctrl.data.successHandler(ctrl.projectName, ctrl.project).success(function (data){
+ $uibModalInstance.close();
+ })
}else{
- ctrl.data.successHandler(ctrl.project);
+ ctrl.data.successHandler(ctrl.project).success(function (data){
+ $uibModalInstance.close();
+ })
}
}else{
ctrl.showCreateError = true;
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html
index 4f0a580..d6d4257 100644
--- a/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html
+++ b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html
@@ -225,14 +225,10 @@
</div>
</div>
<div class="row" style="margin-bottom:24px;"></div>
-<div class='clo-md-12'>
- <div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
- <span class="pull-right">&nbsp;{{ctrl.error}}</span>
- <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
- </div>
- <div ng-show="ctrl.showSuccess" class="alert alert-success" role="alert">
- <span class="pull-right">&nbsp;{{ctrl.success}}</span>
- <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span>
- </div>
-</div>
+<div ng-class="{'show': ctrl.showError}" id="toast" class="error">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true" ></span>
+ {{ctrl.error}}</div>
+<div ng-class="{'show': ctrl.showSuccess}" id="toast" class="success">
+ <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
+ {{ctrl.success}}</div>
<div class="row" style="margin-bottom:24px;"></div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js
index a0cd5eb..e17718f 100644
--- a/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js
+++ b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js
@@ -21,7 +21,7 @@
ScenarioController.$inject = [
'$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert',
- 'confirmModal', 'authenticate'
+ 'confirmModal', 'authenticate', '$timeout'
];
/**
@@ -30,7 +30,7 @@
* through Scenario declared in TestAPI.
*/
function ScenarioController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl,
- raiseAlert, confirmModal, authenticate) {
+ raiseAlert, confirmModal, authenticate, $timeout) {
var ctrl = this;
ctrl.name = $state.params['name'];
ctrl.url = testapiApiUrl + '/scenarios?name=' + ctrl.name;
@@ -73,7 +73,18 @@
ctrl.buttonInstaller = true
ctrl.buttonVersion = true
ctrl.buttonProject = true
+ ctrl.toastError = toastError
+ ctrl.toastSuccess = toastSuccess
+ function toastError() {
+ ctrl.showError = true
+ $timeout(function(){ ctrl.showError = false;}, 3000);
+ }
+
+ function toastSuccess() {
+ ctrl.showSuccess = true
+ $timeout(function(){ ctrl.showSuccess = false;}, 3000);
+ }
/**
* This will contact the TestAPI to get a listing of declared projects.
*/
@@ -84,8 +95,8 @@
ctrl.data = data;
}).catch(function (error) {
ctrl.data = null;
- ctrl.showError = true;
ctrl.error = error.statusText
+ ctrl.toastError()
});
}
@@ -203,13 +214,13 @@
function deleteInstaller(data){
ctrl.installerReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/installers"
$http.delete(ctrl.installerReqest, {data: data.installers, headers: {'Content-Type': 'application/json'}}).success(function (data){
- ctrl.showSuccess = true ;
ctrl.success = "Installer is successfully deleted."
+ ctrl.toastSuccess();
ctrl.loadDetails();
})
.catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError()
});
}
@@ -225,16 +236,18 @@
function addInstaller(installer){
var installers = []
installers.push(installer)
- ctrl.installerReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/installers"
- $http.post(ctrl.installerReqest, installers).success(function (data){
- ctrl.showSuccess = true ;
+ ctrl.installerRequestUrl = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/installers"
+ ctrl.installerRequest = $http.post(ctrl.installerRequestUrl, installers)
+ ctrl.installerRequest.success(function (data){
ctrl.success = "Installers are successfully updated."
ctrl.loadDetails();
+ ctrl.toastSuccess();
})
.catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
+ return ctrl.installerRequest
}
function openAddInstaller(){
@@ -254,16 +267,18 @@
}
function addVersion(versions, installer){
- ctrl.versionReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/versions?installer="+installer
- $http.post(ctrl.versionReqest, versions).success(function (data){
- ctrl.showSuccess = true ;
+ ctrl.versionRequestUrl = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/versions?installer="+installer
+ ctrl.versionRequest = $http.post(ctrl.versionRequestUrl, versions)
+ ctrl.versionRequest.success(function (data){
ctrl.success = "Versions are successfully updated."
ctrl.loadDetails();
+ ctrl.toastSuccess()
})
.catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError()
});
+ return ctrl.versionRequest;
}
function openDeleteVersionModal(version, installer){
@@ -279,13 +294,13 @@
function deleteVersion(data){
ctrl.versionReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/versions?installer="+data.installer
$http.delete(ctrl.versionReqest, {data: data.version, headers: {'Content-Type': 'application/json'}}).success(function (data){
- ctrl.showSuccess = true ;
ctrl.success = "Versions are successfully deleted."
ctrl.loadDetails();
+ ctrl.toastSuccess();
})
.catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
}
@@ -307,16 +322,18 @@
}
function addProject(project, version, installer){
- ctrl.projectReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/projects?installer="+installer+"&version="+version
- $http.post(ctrl.projectReqest, project).success(function (data){
- ctrl.showSuccess = true ;
+ ctrl.projectRequestUrl = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/projects?installer="+installer+"&version="+version
+ ctrl.projectRequest= $http.post(ctrl.projectRequestUrl, project)
+ ctrl.projectRequest.success(function (data){
ctrl.success = "Projects are successfully updated."
ctrl.loadDetails();
+ ctrl.toastSuccess();
})
.catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
+ return ctrl.projectRequest;
}
function openAddProjectModal(version, installer){
@@ -338,16 +355,18 @@
}
function addCustom(custom,project,version,installer){
- ctrl.customReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/customs?installer="+installer+"&version="+version+"&project="+ project
- $http.post(ctrl.customReqest, custom).success(function (data){
- ctrl.showSuccess = true ;
+ ctrl.customRequestUrl = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/customs?installer="+installer+"&version="+version+"&project="+ project
+ ctrl.customRequest = $http.post(ctrl.customRequestUrl, custom)
+ ctrl.customRequest.success(function (data){
ctrl.success = "Customs are successfully updated."
ctrl.loadDetails();
+ ctrl.toastSuccess();
})
.catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
+ return ctrl.customRequest
}
function openDeleteCustomModal(custom,project,version,installer){
@@ -365,13 +384,13 @@
function deleteCustom(data){
ctrl.customReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/customs?installer="+data.installer+"&version="+data.version+"&project="+ data.project
$http.delete(ctrl.customReqest, {data: data.customs, headers: {'Content-Type': 'application/json'}}).success(function (data){
- ctrl.showSuccess = true ;
ctrl.success = "Customs are successfully deleted."
ctrl.loadDetails();
+ ctrl.toastSuccess();
})
.catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
}
@@ -408,13 +427,13 @@
function deleteProject(data){
ctrl.projectReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/projects?installer="+data.installer+"&version="+data.version
$http.delete(ctrl.projectReqest, {data: data.projects, headers: {'Content-Type': 'application/json'}}).success(function (data){
- ctrl.showSuccess = true ;
- ctrl.success = "Projects are successfully Deleted."
+ ctrl.success = "Projects are successfully Deleted.";
+ ctrl.toastSuccess();
ctrl.loadDetails();
})
.catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
}
@@ -443,8 +462,11 @@
ctrl.customs = custom.split(/[ ,]+/).filter(Boolean);
}
console.log(ctrl.customs)
- ctrl.data.successHandler(ctrl.customs,ctrl.data.project,ctrl.data.version,ctrl.data.installer);
- $uibModalInstance.dismiss('cancel');
+ ctrl.data.successHandler(
+ ctrl.customs, ctrl.data.project,
+ ctrl.data.version,ctrl.data.installer).success(function(){
+ $uibModalInstance.dismiss('cancel');
+ });
}
@@ -486,8 +508,10 @@
*/
function confirm() {
ctrl.projects.push(ctrl.project)
- ctrl.data.successHandler(ctrl.projects, ctrl.data.version, ctrl.data.installer);
- $uibModalInstance.dismiss('cancel');
+ ctrl.data.successHandler(
+ ctrl.projects, ctrl.data.version, ctrl.data.installer).success( function(){
+ $uibModalInstance.dismiss('cancel');
+ });
}
@@ -545,8 +569,9 @@
*/
function confirm() {
ctrl.versions.push(ctrl.version)
- ctrl.data.successHandler(ctrl.versions, ctrl.data.installer);
- $uibModalInstance.dismiss('cancel');
+ ctrl.data.successHandler(ctrl.versions, ctrl.data.installer).success(function(){
+ $uibModalInstance.dismiss('cancel');
+ });
}
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html b/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html
index bde946c..8d23449 100644
--- a/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html
+++ b/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html
@@ -10,16 +10,12 @@
<i class="fa fa-plus"></i>Create</button>
</div>
</div>
-<div class='clo-md-12'>
- <div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
- <span class="pull-right">&nbsp;{{ctrl.error}}</span>
- <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span>
- </div>
- <div ng-show="ctrl.showCreateSuccess" class="alert alert-success" role="alert">
- <span class="pull-right">&nbsp;{{ctrl.success}}</span>
- <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span>
- </div>
-</div>
+<div ng-class="{'show': ctrl.showError}" id="toast" class="error">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true" ></span>
+ {{ctrl.error}}</div>
+<div ng-class="{'show': ctrl.showSuccess}" id="toast" class="success">
+ <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
+ {{ctrl.success}}</div>
<div class='clo-md-12' style="padding-right:0px">
<div class="table-responsive">
<table class="table table-bordered table-hover" ng-data="ctrl.data.scenarios">
diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js b/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js
index 240287c..0aa5bf0 100644
--- a/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js
+++ b/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js
@@ -21,7 +21,7 @@
ScenariosController.$inject = [
'$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl',
- 'raiseAlert', 'confirmModal', 'sortService'
+ 'raiseAlert', 'confirmModal', 'sortService', '$timeout'
];
/**
@@ -30,7 +30,7 @@
* through projects declared in TestAPI.
*/
function ScenariosController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl,
- raiseAlert, confirmModal, sortService) {
+ raiseAlert, confirmModal, sortService, $timeout) {
var ctrl = this;
ctrl.url = testapiApiUrl + '/scenarios';
@@ -47,6 +47,18 @@
ctrl.sortBy = sortBy
ctrl.checkBox = [];
ctrl.sortName = false
+ ctrl.toastError = toastError
+ ctrl.toastSuccess = toastSuccess
+
+ function toastError() {
+ ctrl.showError = true
+ $timeout(function(){ ctrl.showError = false;}, 3000);
+ }
+
+ function toastSuccess() {
+ ctrl.showSuccess = true
+ $timeout(function(){ ctrl.showSuccess = false;}, 3000);
+ }
function openUpdateModal(name){
$uibModal.open({
@@ -78,12 +90,12 @@
var scenarioURL = ctrl.url+"/"+name;
ctrl.scenarioRequest =
$http.delete(scenarioURL).success(function (data){
- ctrl.showCreateSuccess = true;
ctrl.success = "Scenario is successfully deleted.";
ctrl.listScenarios();
+ ctrl.toastSuccess();
}).catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError()
});
}
@@ -117,15 +129,21 @@
var body = {
"name": newName
}
- ctrl.scenarioRequest =
- $http.put(scenarioURL, body).success(function (data){
- ctrl.showCreateSuccess = true;
+ if(newName){
+ ctrl.scenarioRequest = $http.put(scenarioURL, body)
+ ctrl.scenarioRequest.success(function (data){
ctrl.success = "Scenario is successfully Updated."
- ctrl.listScenarios()
+ ctrl.listScenarios();
+ ctrl.toastSuccess();
}).catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
+ return ctrl.scenarioRequest
+ }else{
+ ctrl.error = "Name is missing";
+ ctrl.toastError();
+ }
}
function viewScenario(name){
@@ -133,14 +151,17 @@
}
function createScenario(scenario) {
- ctrl.scenarioRequest =
- $http.post(ctrl.url, scenario).success(function (data){
- ctrl.showCreateSuccess = true;
- ctrl.success = "Scenario is successfully created."
+ ctrl.scenarioRequest = $http.post(ctrl.url, scenario)
+
+ ctrl.scenarioRequest.success(function (data){
+ ctrl.success = "Scenario is successfully created.";
+ ctrl.toastSuccess();
}).catch(function (data) {
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
+
+ return ctrl.scenarioRequest;
}
function listScenarios() {
@@ -151,8 +172,8 @@
ctrl.sortBy()
}).catch(function (data) {
ctrl.data = null;
- ctrl.showError = true;
ctrl.error = data.statusText;
+ ctrl.toastError();
});
}
@@ -183,8 +204,8 @@
* edit the project's details
*/
angular.module('testapiApp').controller('scenarioModalController', scenarioModalController);
- scenarioModalController.$inject = ['$scope', '$uibModal', '$uibModalInstance', 'data'];
- function scenarioModalController($scope, $uibModal, $uibModalInstance, data) {
+ scenarioModalController.$inject = ['$scope', '$uibModal', '$uibModalInstance', 'data', '$q'];
+ function scenarioModalController($scope, $uibModal, $uibModalInstance, data, $q) {
var ctrl = this;
ctrl.confirm = confirm;
ctrl.cancel = cancel;
@@ -201,8 +222,9 @@
* inputs.
*/
function confirm() {
- ctrl.data.successHandler(ctrl.scenario);
- $uibModalInstance.dismiss('cancel');
+ ctrl.data.successHandler(ctrl.scenario).success(function(){
+ $uibModalInstance.dismiss('cancel');
+ });
}
@@ -215,6 +237,9 @@
function handleModalData(installer){
ctrl.scenario.installers.push(installer)
+ var deferred = $q.defer();
+ deferred.resolve();
+ return deferred.promise;
}
function openInstallerModal(){
@@ -259,8 +284,9 @@
* inputs.
*/
function confirm() {
- ctrl.data.successHandler(ctrl.installer);
- $uibModalInstance.dismiss('cancel');
+ ctrl.data.successHandler(ctrl.installer).success(function(){
+ $uibModalInstance.dismiss('cancel');
+ });
}
@@ -472,9 +498,9 @@
* inputs.
*/
function confirm() {
- ctrl.data.successHandler(ctrl.name,ctrl.data.name);
- $uibModalInstance.dismiss('cancel');
-
+ ctrl.data.successHandler(ctrl.name,ctrl.data.name).success( function() {
+ $uibModalInstance.dismiss('cancel');
+ })
}
/**
diff --git a/testapi/opnfv_testapi/ui/package.json b/testapi/opnfv_testapi/ui/package.json
index dc99239..2d4eb6e 100644
--- a/testapi/opnfv_testapi/ui/package.json
+++ b/testapi/opnfv_testapi/ui/package.json
@@ -3,6 +3,7 @@
"grunt": "~1.0.1",
"grunt-contrib-connect": "^1.0.2",
"grunt-contrib-copy": "^1.0.0",
+ "grunt-convert": "^0.1.12",
"grunt-karma": "~2.0.0",
"grunt-protractor-coverage": "^0.2.18",
"grunt-protractor-runner": "~5.0.0",
diff --git a/testapi/requirements.txt b/testapi/requirements.txt
index f752a64..7f50fd7 100644
--- a/testapi/requirements.txt
+++ b/testapi/requirements.txt
@@ -9,4 +9,5 @@ epydoc>=0.3.1
six>=1.9.0 # MIT
motor # Apache-2.0
python-cas
-requests[security] \ No newline at end of file
+requests[security]
+futures \ No newline at end of file
diff --git a/testapi/testapi-client/etc/client.creds b/testapi/testapi-client/etc/client.creds
index a082047..ee2a0ab 100644
--- a/testapi/testapi-client/etc/client.creds
+++ b/testapi/testapi-client/etc/client.creds
@@ -1,3 +1,4 @@
export testapi_url=http://localhost:8000/api/v1
export testapi_cas_signin_return=/auth/signin_return
-export testapi_cas_auth_url=https://identity.linuxfoundation.org/user/login?destination=cas/login%3Fservice%3D \ No newline at end of file
+export testapi_cas_auth_url=https://identity.linuxfoundation.org/user/login?destination=cas/login%3Fservice%3D
+export testapi_token=changeme \ No newline at end of file
diff --git a/testapi/testapi-client/setup.cfg b/testapi/testapi-client/setup.cfg
index b89fba4..ee1ba54 100644
--- a/testapi/testapi-client/setup.cfg
+++ b/testapi/testapi-client/setup.cfg
@@ -64,6 +64,10 @@ testapi =
deployresult get = testapiclient.cli.deployresults:DeployresultGet
deployresult getone = testapiclient.cli.deployresults:DeployresultGetOne
+ result create = testapiclient.cli.results:ResultCreate
+ result get = testapiclient.cli.results:ResultGet
+ result getone = testapiclient.cli.results:ResultGetOne
+
[egg_info]
tag_build =
tag_date = 0
diff --git a/testapi/testapi-client/testapiclient/cli/deployresults.py b/testapi/testapi-client/testapiclient/cli/deployresults.py
index a6fe13e..1ca0bef 100644
--- a/testapi/testapi-client/testapiclient/cli/deployresults.py
+++ b/testapi/testapi-client/testapiclient/cli/deployresults.py
@@ -2,6 +2,7 @@ import json
from testapiclient.utils import command
from testapiclient.utils import urlparse
+from testapiclient.models import deployresult
def deployresults_url():
@@ -85,13 +86,10 @@ class DeployresultCreate(command.ShowOne):
parser.add_argument('deployresult',
type=json.loads,
help='Deployresult create request format:\n'
- '\'{"job_name" : "","scenario" : "",'
- '"stop_date" : "", "build_id" : "",'
- '"upstream_job_name": "",'
- '"version" : "", "pod_name" : "",'
- '"criteria" : "", "installer" : "",'
- '"upstream_build_id" : "",'
- '"start_date" : "", "details" : ""}\'')
+ '\'{}\''.format(json.dumps(
+ deployresult.DeployResultCreateRequest(
+ ).__dict__
+ )))
return parser
def take_action(self, parsed_args):
diff --git a/testapi/testapi-client/testapiclient/cli/pods.py b/testapi/testapi-client/testapiclient/cli/pods.py
index 8d0970b..a7706f6 100644
--- a/testapi/testapi-client/testapiclient/cli/pods.py
+++ b/testapi/testapi-client/testapiclient/cli/pods.py
@@ -1,7 +1,9 @@
import json
+from testapiclient.client import pods
from testapiclient.utils import command
from testapiclient.utils import urlparse
+from testapiclient.models import pods as pm
def pods_url():
@@ -60,15 +62,17 @@ class PodCreate(command.ShowOne):
parser.add_argument('pod',
type=json.loads,
help='Pod create request format :\n'
- '\'{"role": "", "name": "", "details": "", '
- '"mode": ""}\',\n role should be either '
+ '\'{}\''.format(json.dumps(
+ pm.PodCreateRequest().__dict__
+ )) +
+ '\n role should be either '
'"community-ci" or "production-ci", and '
'mode should be either "metal" or "virtual.')
return parser
def take_action(self, parsed_args):
- return self.format_output(
- self.app.client_manager.post(pods_url(), parsed_args.pod))
+ client = pods.PodsClient(client_manager=self.app.client_manager)
+ return self.format_output(client.create(parsed_args.pod))
class PodDelete(command.Command):
diff --git a/testapi/testapi-client/testapiclient/cli/projects.py b/testapi/testapi-client/testapiclient/cli/projects.py
index 510acc8..2fa5b5b 100644
--- a/testapi/testapi-client/testapiclient/cli/projects.py
+++ b/testapi/testapi-client/testapiclient/cli/projects.py
@@ -2,6 +2,7 @@ import json
from testapiclient.utils import command
from testapiclient.utils import urlparse
+from testapiclient.models import project
def projects_url():
@@ -51,9 +52,10 @@ class ProjectCreate(command.ShowOne):
parser = super(ProjectCreate, self).get_parser(prog_name)
parser.add_argument('project',
type=json.loads,
- help='Project create request format :{'
- ' "name": (required)"", '
- '"description": (optional)""}')
+ help='Project create request format :\n'
+ '\'{}\''.format(json.dumps(
+ project.ProjectCreateRequest().__dict__
+ )))
return parser
def take_action(self, parsed_args):
@@ -83,9 +85,10 @@ class ProjectPut(command.ShowOne):
help='Update project by name')
parser.add_argument('project',
type=json.loads,
- help='Project Update request format :{'
- '"name": (required)"", '
- '"description": (optional)""}')
+ help='Project Update request format :\n'
+ '\'{}\''.format(json.dumps(
+ project.ProjectCreateRequest().__dict__
+ )))
return parser
def take_action(self, parsed_args):
diff --git a/testapi/testapi-client/testapiclient/cli/results.py b/testapi/testapi-client/testapiclient/cli/results.py
new file mode 100644
index 0000000..5500501
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/cli/results.py
@@ -0,0 +1,97 @@
+import json
+
+from testapiclient.utils import command
+from testapiclient.utils import urlparse
+from testapiclient.models import result
+
+
+def results_url():
+ return urlparse.resource_join('results')
+
+
+def result_url(parsed_args):
+ return urlparse.path_join(results_url(), parsed_args.result_id)
+
+
+class ResultGet(command.Lister):
+
+ def get_parser(self, prog_name):
+ parser = super(ResultGet, self).get_parser(prog_name)
+ parser.add_argument('-case',
+ help='Search results using tesetcase')
+ parser.add_argument('-build-tag',
+ help='Search results using build tag')
+ parser.add_argument('-from',
+ help='Search results using from date')
+ parser.add_argument('-last',
+ help='Search results using last date')
+ parser.add_argument('-scenario',
+ help='Search results using scenario')
+ parser.add_argument('-period',
+ help='Search results using period')
+ parser.add_argument('-project',
+ help='Search results using project')
+ parser.add_argument('-to',
+ help='Search results using to')
+ parser.add_argument('---version',
+ help='Search results using version')
+ parser.add_argument('-criteria',
+ help='Search results using version')
+ parser.add_argument('-installer',
+ help='Search results using installer')
+ parser.add_argument('-pod',
+ help='Search results using pod')
+ parser.add_argument('-page',
+ help='Search results using page')
+ return parser
+
+ def take_action(self, parsed_args):
+ columns = (
+ '_id',
+ 'pod_name',
+ 'project_name',
+ 'case_name',
+ 'installer',
+ 'version',
+ 'scenario',
+ 'criteria',
+ 'start_date'
+ )
+ data = self.app.client_manager.get(
+ urlparse.query_by(results_url(),
+ ['case', 'build_tag', 'from', 'last',
+ 'scenario', 'period', 'project',
+ 'to', 'version',
+ 'criteria', 'installer', 'pod', 'page'],
+ parsed_args))
+ return self.format_output(columns, data.get('results', []))
+
+
+class ResultGetOne(command.ShowOne):
+
+ def get_parser(self, prog_name):
+ parser = super(ResultGetOne, self).get_parser(prog_name)
+ parser.add_argument('result_id',
+ help='Search result by result id')
+ return parser
+
+ def take_action(self, parsed_args):
+ return self.format_output(
+ self.app.client_manager.get(result_url(parsed_args)))
+
+
+class ResultCreate(command.ShowOne):
+
+ def get_parser(self, prog_name):
+ parser = super(ResultCreate, self).get_parser(prog_name)
+ parser.add_argument('result',
+ type=json.loads,
+ help='Result create request format:\n'
+ '\'{}\''.format(json.dumps(
+ result.ResultCreateRequest().__dict__)))
+ return parser
+
+ def take_action(self, parsed_args):
+ return self.format_output(
+ self.app.client_manager.post(
+ results_url(), parsed_args.result))
diff --git a/testapi/testapi-client/testapiclient/cli/scenarios.py b/testapi/testapi-client/testapiclient/cli/scenarios.py
index 507705a..197ee0c 100644
--- a/testapi/testapi-client/testapiclient/cli/scenarios.py
+++ b/testapi/testapi-client/testapiclient/cli/scenarios.py
@@ -2,6 +2,7 @@ import json
from testapiclient.utils import command
from testapiclient.utils import urlparse
+from testapiclient.models import scenario
def scenarios_url():
@@ -64,22 +65,37 @@ class ScenarioCreate(command.ShowOne):
parser.add_argument('scenario',
type=json.loads,
help='Scenario create request format :\n'
- '\'{ "installers": [], "name": ""}\',\n'
- 'Intaller create request format :\n'
- '\'{"installer": "","versions": []}\',\n'
- 'Version create request format :\n'
- '\'{"owner": "","version": "",'
- '"projects": []}\',\n'
- 'Project create request format :\n'
- '\'{"project": "","customs": [],'
- '"scores": [],'
- '"trust_indicators": []}\',\n'
- 'Custom create request format :\n'
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioCreateRequest(
+ ).__dict__
+ )) +
+ '\n Intaller create request format :\n'
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioInstallerCreateRequest(
+ ).__dict__
+ )) +
+ '\n Version create request format :\n'
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioVersionCreateRequest(
+ ).__dict__
+ )) +
+ '\n Project create request format :\n'
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioProjectCreateRequest(
+ ).__dict__
+ )) +
+ '\n Custom create request format :\n'
'\'["asf","saf"]\',\n'
- 'Score create request format :\n'
- '\'{"date": "", "score": ""}\',\n'
- 'Trust Indicators create request format :\n'
- '\'{"date": "", "status": ""}\'')
+ '\n Score create request format :\n'
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioScoreCreateRequest(
+ ).__dict__
+ )) +
+ '\nTrustIndicator create request format:\n'
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioTICreateRequest(
+ ).__dict__
+ )))
return parser
def take_action(self, parsed_args):
@@ -110,23 +126,38 @@ class ScenarioPut(command.ShowOne):
help='Update scenario by name')
parser.add_argument('scenario',
type=json.loads,
- help='Scenario create request format :\n'
- '\'{ "installers": [], "name": ""}\',\n'
- 'Intaller create request format :\n'
- '\'{"installer": "","versions": []}\',\n'
- 'Version create request format :\n'
- '\'{"owner": "","version": "",'
- '"projects": []}\',\n'
- 'Project create request format :\n'
- '\'{"project": "","customs": [],'
- '"scores": [],'
- '"trust_indicators": []}\',\n'
- 'Custom create request format :\n'
+ help='Scenario create request format :\n' +
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioCreateRequest(
+ ).__dict__
+ )) +
+ '\n Intaller create request format :\n'
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioInstallerCreateRequest(
+ ).__dict__
+ )) +
+ '\n Version create request format :\n'
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioVersionCreateRequest(
+ ).__dict__
+ )) +
+ '\n Project create request format :\n'
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioProjectCreateRequest(
+ ).__dict__
+ )) +
+ '\n Custom create request format :\n'
'\'["asf","saf"]\',\n'
- 'Score create request format :\n'
- '\'{"date": "", "score": ""}\',\n'
- 'Trust Indicators create request format :\n'
- '\'{"date": "", "status": ""}\'')
+ '\n Score create request format :\n'
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioScoreCreateRequest(
+ ).__dict__
+ )) +
+ '\nTrustIndicator create request format:\n'
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioTICreateRequest(
+ ).__dict__
+ )))
return parser
def take_action(self, parsed_args):
@@ -145,7 +176,10 @@ class InstallerCreate(command.Command):
parser.add_argument('installer',
type=json.loads,
help='Intaller create request format :\n'
- '\'[{"installer": "","versions": []}]\',\n')
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioInstallerCreateRequest(
+ ).__dict__
+ )))
return parser
def take_action(self, parsed_args):
@@ -186,7 +220,10 @@ class InstallerPut(command.Command):
parser.add_argument('installer',
type=json.loads,
help='Intaller create request format :\n'
- '\'[{"installer": "","versions": []}]\',\n')
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioInstallerCreateRequest(
+ ).__dict__
+ )))
return parser
def take_action(self, parsed_args):
@@ -209,10 +246,10 @@ class VersionCreate(command.Command):
parser.add_argument('version',
type=json.loads,
help='version create request format :\n'
- '\'[{"owner":(string),'
- '"version": (string),'
- '"projects": (array[ScenarioProject])'
- '}]\',\n')
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioVersionCreateRequest(
+ ).__dict__
+ )))
return parser
def take_action(self, parsed_args):
@@ -261,10 +298,10 @@ class VersionPut(command.Command):
parser.add_argument('version',
type=json.loads,
help='version update request format :\n'
- '\'[{"owner":(string),'
- '"version": (string),'
- '"projects": (array[ScenarioProject])'
- '}]\',\n')
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioVersionCreateRequest(
+ ).__dict__
+ )))
return parser
def take_action(self, parsed_args):
@@ -320,10 +357,10 @@ class ProjectCreate(command.Command):
parser.add_argument('project',
type=json.loads,
help='Project create request format :\n'
- '\'[{ "project" (string),'
- '"scores": (array[ScenarioScore]),'
- '"trust_indicators": (array[ScenarioTI]),'
- '"customs": (array[string]) }]\',\n')
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioProjectCreateRequest(
+ ).__dict__
+ )))
return parser
def take_action(self, parsed_args):
@@ -378,10 +415,10 @@ class ProjectPut(command.Command):
parser.add_argument('project',
type=json.loads,
help='Project update request format :\n'
- '\'[{ "project" (string),'
- '"scores": (array[ScenarioScore]),'
- '"trust_indicators": (array[ScenarioTI]),'
- '"customs": (array[string]) }]\',\n')
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioProjectCreateRequest(
+ ).__dict__
+ )))
return parser
def take_action(self, parsed_args):
@@ -511,8 +548,10 @@ class TrustIndicatorCreate(command.Command):
parser.add_argument('trust_indicator',
type=json.loads,
help='trust indicator create request format :\n'
- '\'{ "date": (string, optional),'
- '"status": (string, optional) }\',\n')
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioTICreateRequest(
+ ).__dict__
+ )))
return parser
def take_action(self, parsed_args):
@@ -547,8 +586,10 @@ class ScoreCreate(command.Command):
parser.add_argument('score',
type=json.loads,
help='score create request format :\n'
- '\'{ "date": (string, optional),'
- '"score" : (string, optional) }\',\n')
+ '\'{}\''.format(json.dumps(
+ scenario.ScenarioScoreCreateRequest(
+ ).__dict__
+ )))
return parser
def take_action(self, parsed_args):
diff --git a/testapi/testapi-client/testapiclient/cli/testcases.py b/testapi/testapi-client/testapiclient/cli/testcases.py
index 6c97edb..3052c18 100644
--- a/testapi/testapi-client/testapiclient/cli/testcases.py
+++ b/testapi/testapi-client/testapiclient/cli/testcases.py
@@ -2,6 +2,7 @@ import json
from testapiclient.utils import command
from testapiclient.utils import urlparse
+from testapiclient.models import testcase
def testcases_url(name):
@@ -60,12 +61,9 @@ class TestcaseCreate(command.ShowOne):
parser.add_argument('testcase',
type=json.loads,
help='Testcase create request format:\n'
- '\'{"run": "", "name": "", "ci_loop": "",'
- '"tags": "",\n "url": "", "blocking": "",'
- '"domains": "", "dependencies": "",\n '
- '"version": "", "criteria": "", "tier": "",'
- '"trust": "",\n "catalog_description": "",'
- '"description": ""}\'')
+ '\'{}\''.format(json.dumps(
+ testcase.TestCaseCreateRequest().__dict__
+ )))
return parser
def take_action(self, parsed_args):
@@ -105,12 +103,9 @@ class TestcasePut(command.ShowOne):
parser.add_argument('testcase',
type=json.loads,
help='Testcase Update request format:\n'
- '\'{"run": "", "name": "", "ci_loop": "",'
- '"tags": "",\n "url": "", "blocking": "",'
- '"domains": "", "dependencies": "",\n '
- '"version": "", "criteria": "", "tier": "",'
- '"trust": "",\n "catalog_description": "",'
- '"description": ""}\'')
+ '\'{}\''.format(json.dumps(
+ testcase.TestCaseCreateRequest().__dict__
+ )))
return parser
def take_action(self, parsed_args):
diff --git a/testapi/testapi-client/testapiclient/client/__init__.py b/testapi/testapi-client/testapiclient/client/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/client/__init__.py
diff --git a/testapi/testapi-client/testapiclient/client/base.py b/testapi/testapi-client/testapiclient/client/base.py
new file mode 100644
index 0000000..c45c9b7
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/client/base.py
@@ -0,0 +1,23 @@
+from testapiclient.utils import clientmanager
+from testapiclient.utils import urlparse
+
+
+class AuthOption(object):
+ def __init__(self, user=None, password=None):
+ self.u = user
+ self.p = password
+
+
+class Client(object):
+
+ resource = ''
+
+ def __init__(self, user=None, password=None, client_manager=None):
+ self.url = urlparse.resource_join(self.resource)
+ if client_manager:
+ self.clientmanager = client_manager
+ else:
+ self.clientmanager = clientmanager.ClientManager(
+ AuthOption(user, password))
+ if self.clientmanager.auth_required:
+ self.clientmanager.auth()
diff --git a/testapi/testapi-client/testapiclient/client/deploy_results.py b/testapi/testapi-client/testapiclient/client/deploy_results.py
new file mode 100644
index 0000000..b0724b0
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/client/deploy_results.py
@@ -0,0 +1,28 @@
+import json
+
+from testapiclient.client import base
+from testapiclient.utils import urlparse
+
+
+class DeployResultsClient(base.Client):
+ resource = 'deployresults'
+
+ def __init__(self, **kwargs):
+ super(DeployResultsClient, self).__init__(**kwargs)
+
+ def create(self, testcase_req):
+ return self.clientmanager.post(self.url, testcase_req)
+
+ def get(self, **queries):
+ if queries:
+ return json.dumps(
+ self.clientmanager.get(
+ urlparse.query_join(self.url, **queries))['deployresults'])
+ else:
+ return json.dumps(
+ self.clientmanager.get(self.url)['deployresults'])
+
+ def get_one(self, id):
+ return json.dumps(
+ self.clientmanager.get(
+ urlparse.path_join(self.url, id)))
diff --git a/testapi/testapi-client/testapiclient/client/pods.py b/testapi/testapi-client/testapiclient/client/pods.py
new file mode 100644
index 0000000..d08114f
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/client/pods.py
@@ -0,0 +1,31 @@
+import json
+
+from testapiclient.client import base
+from testapiclient.utils import urlparse
+
+
+class PodsClient(base.Client):
+ resource = 'pods'
+
+ def __init__(self, **kwargs):
+ super(PodsClient, self).__init__(**kwargs)
+
+ def create(self, pod_req):
+ return self.clientmanager.post(self.url, pod_req)
+
+ def get(self, **queries):
+ if queries:
+ return json.dumps(
+ self.clientmanager.get(
+ urlparse.query_join(self.url, **queries))['pods'])
+ else:
+ return json.dumps(
+ self.clientmanager.get(self.url)['pods'])
+
+ def get_one(self, name):
+ return json.dumps(self.clientmanager.get(
+ urlparse.path_join(self.url, name)))
+
+ def delete(self, name):
+ return self.clientmanager.delete(
+ urlparse.path_join(self.url, name))
diff --git a/testapi/testapi-client/testapiclient/client/projects.py b/testapi/testapi-client/testapiclient/client/projects.py
new file mode 100644
index 0000000..63d00fe
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/client/projects.py
@@ -0,0 +1,35 @@
+import json
+
+from testapiclient.client import base
+from testapiclient.utils import urlparse
+
+
+class ProjectsClient(base.Client):
+ resource = 'projects'
+
+ def __init__(self, **kwargs):
+ super(ProjectsClient, self).__init__(**kwargs)
+
+ def create(self, project_req):
+ return self.clientmanager.post(self.url, project_req)
+
+ def get(self, **queries):
+ if queries:
+ return json.dumps(
+ self.clientmanager.get(
+ urlparse.query_join(self.url, **queries))['projects'])
+ else:
+ return json.dumps(
+ self.clientmanager.get(self.url)['projects'])
+
+ def get_one(self, name):
+ return json.dumps(self.clientmanager.get(
+ urlparse.path_join(self.url, name)))
+
+ def delete(self, name):
+ return self.clientmanager.delete(
+ urlparse.path_join(self.url, name))
+
+ def update(self, name, project_req):
+ return self.clientmanager.put(
+ urlparse.path_join(self.url, name), project_req)
diff --git a/testapi/testapi-client/testapiclient/client/results.py b/testapi/testapi-client/testapiclient/client/results.py
new file mode 100644
index 0000000..7d9ad0e
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/client/results.py
@@ -0,0 +1,28 @@
+import json
+
+from testapiclient.client import base
+from testapiclient.utils import urlparse
+
+
+class ResultsClient(base.Client):
+ resource = 'results'
+
+ def __init__(self, **kwargs):
+ super(ResultsClient, self).__init__(**kwargs)
+
+ def create(self, testcase_req):
+ return self.clientmanager.post(self.url, testcase_req)
+
+ def get(self, **queries):
+ if queries:
+ return json.dumps(
+ self.clientmanager.get(
+ urlparse.query_join(self.url, **queries))['results'])
+ else:
+ return json.dumps(
+ self.clientmanager.get(self.url)['results'])
+
+ def get_one(self, id):
+ return json.dumps(
+ self.clientmanager.get(
+ urlparse.path_join(self.url, id)))
diff --git a/testapi/testapi-client/testapiclient/client/scenarios.py b/testapi/testapi-client/testapiclient/client/scenarios.py
new file mode 100644
index 0000000..e5ce2f1
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/client/scenarios.py
@@ -0,0 +1,177 @@
+import json
+
+from testapiclient.client import base
+from testapiclient.utils import urlparse
+
+
+class ScenariosClient(base.Client):
+ resource = 'scenarios'
+
+ def __init__(self, **kwargs):
+ super(ScenariosClient, self).__init__(**kwargs)
+
+ def create(self, scenario_req):
+ return self.clientmanager.post(self.url, scenario_req)
+
+ def get(self, **queries):
+ if queries:
+ return json.dumps(
+ self.clientmanager.get(
+ urlparse.query_join(self.url, **queries))['scenarios'])
+ else:
+ return json.dumps(
+ self.clientmanager.get(self.url)['scenarios'])
+
+ def get_one(self, scenario_name):
+ return json.dumps(
+ self.clientmanager.get(
+ urlparse.path_join(
+ self.url, scenario_name)))
+
+ def delete(self, scenario_name):
+ return self.clientmanager.delete(
+ urlparse.path_join(
+ self.url, scenario_name))
+
+ def update(self, scenario_name, scenario_req):
+ return self.clientmanager.put(
+ urlparse.path_join(
+ self.url, scenario_name), scenario_req)
+
+
+class InstallersClient(base.Client):
+ resource = 'scenarios/{}/installers'
+
+ def __init__(self, **kwargs):
+ super(InstallersClient, self).__init__(**kwargs)
+
+ def delete(self, scenario_name, name):
+ return self.clientmanager.delete(
+ self.url.format(scenario_name), [name])
+
+ def update(self, scenario_name, installer_req):
+ return self.clientmanager.put(
+ self.url.format(scenario_name), installer_req)
+
+ def create(self, scenario_name, installer_req):
+ return self.clientmanager.post(
+ self.url.format(scenario_name), installer_req)
+
+
+class VersionsClient(base.Client):
+ resource = 'scenarios/{}/versions'
+
+ def __init__(self, **kwargs):
+ super(VersionsClient, self).__init__(**kwargs)
+
+ def delete(self, scenario_name, installer, name):
+ queries = {'installer': installer}
+ return self.clientmanager.delete(
+ urlparse.query_join(
+ self.url.format(scenario_name), **queries), name)
+
+ def update(self, scenario_name, installer, version_req):
+ queries = {'installer': installer}
+ return self.clientmanager.put(
+ urlparse.query_join(
+ self.url.format(scenario_name), **queries), version_req)
+
+ def create(self, scenario_name, installer, version_req):
+ queries = {'installer': installer}
+ return self.clientmanager.post(
+ urlparse.query_join(
+ self.url.format(scenario_name), **queries), version_req)
+
+
+class VersionsOwnerClient(base.Client):
+ resource = 'scenarios/{}/owner'
+
+ def __init__(self, **kwargs):
+ super(VersionsOwnerClient, self).__init__(**kwargs)
+
+ def update(self, scenario_name, installer, version, owner):
+ queries = {'installer': installer, 'version': version}
+ return self.clientmanager.put(
+ urlparse.query_join(
+ self.url.format(scenario_name), **queries), owner)
+
+
+class ProjectsClient(base.Client):
+ resource = 'scenarios/{}/projects'
+
+ def __init__(self, **kwargs):
+ super(ProjectsClient, self).__init__(**kwargs)
+
+ def delete(self, scenario_name, installer, version, name):
+ queries = {'installer': installer, 'version': version}
+ return self.clientmanager.delete(
+ urlparse.query_join(
+ self.url.format(scenario_name), **queries), name)
+
+ def update(self, scenario_name, installer, version, project_req):
+ queries = {'installer': installer, 'version': version}
+ return self.clientmanager.put(
+ urlparse.query_join(
+ self.url.format(scenario_name), **queries), project_req)
+
+ def create(self, scenario_name, installer, version, project_req):
+ queries = {'installer': installer, 'version': version}
+ return self.clientmanager.post(
+ urlparse.query_join(
+ self.url.format(scenario_name), **queries), project_req)
+
+
+class TrustIndicatorsClient(base.Client):
+ resource = 'scenarios/{}/trust_indicators'
+
+ def __init__(self, **kwargs):
+ super(TrustIndicatorsClient, self).__init__(**kwargs)
+
+ def create(self, scenario_name, installer, version, project, trust_in_req):
+ queries = {
+ 'installer': installer, 'version': version, 'project': project}
+ return self.clientmanager.post(
+ urlparse.query_join(
+ self.url.format(scenario_name), **queries), trust_in_req)
+
+
+class ScoresClient(base.Client):
+ resource = 'scenarios/{}/scores'
+
+ def __init__(self, **kwargs):
+ super(ScoresClient, self).__init__(**kwargs)
+
+ def create(self, scenario_name, installer, version, project, scores_req):
+ queries = {
+ 'installer': installer, 'version': version, 'project': project}
+ return self.clientmanager.post(
+ urlparse.query_join(
+ self.url.format(scenario_name), **queries), scores_req)
+
+
+class CustomsClient(base.Client):
+ resource = 'scenarios/{}/customs'
+
+ def __init__(self, **kwargs):
+ super(CustomsClient, self).__init__(**kwargs)
+
+ def delete(self, scenario_name, installer, version, project, customs):
+ queries = {
+ 'installer': installer, 'version': version, 'project': project}
+ return self.clientmanager.delete(
+ urlparse.query_join(
+ self.url.format(scenario_name), **queries), customs)
+
+ def update(self, scenario_name, installer, version, project, customs):
+ queries = {
+ 'installer': installer, 'version': version, 'project': project}
+ return self.clientmanager.put(
+ urlparse.query_join(
+ self.url.format(scenario_name), **queries), customs)
+
+ def create(self, scenario_name, installer, version, project, customs):
+ queries = {
+ 'installer': installer, 'version': version, 'project': project}
+ return self.clientmanager.post(
+ urlparse.query_join(
+ self.url.format(scenario_name), **queries), customs)
diff --git a/testapi/testapi-client/testapiclient/client/testcases.py b/testapi/testapi-client/testapiclient/client/testcases.py
new file mode 100644
index 0000000..bb2b6d3
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/client/testcases.py
@@ -0,0 +1,36 @@
+import json
+
+from testapiclient.client import base
+from testapiclient.utils import urlparse
+
+
+class TestcasesClient(base.Client):
+ resource = 'projects/{}/cases'
+
+ def __init__(self, **kwargs):
+ super(TestcasesClient, self).__init__(**kwargs)
+
+ def create(self, project_name, testcase_req):
+ return self.clientmanager.post(
+ self.url.format(project_name), testcase_req)
+
+ def get(self, project_name):
+ return json.dumps(
+ self.clientmanager.get(
+ self.url.format(project_name))['testcases'])
+
+ def get_one(self, project_name, name):
+ return json.dumps(
+ self.clientmanager.get(
+ urlparse.path_join(
+ self.url.format(project_name), name)))
+
+ def delete(self, project_name, name):
+ return self.clientmanager.delete(
+ urlparse.path_join(
+ self.url.format(project_name), name))
+
+ def update(self, project_name, name, testcase_req):
+ return self.clientmanager.put(
+ urlparse.path_join(
+ self.url.format(project_name), name), testcase_req)
diff --git a/testapi/testapi-client/testapiclient/models/__init__.py b/testapi/testapi-client/testapiclient/models/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/models/__init__.py
diff --git a/testapi/testapi-client/testapiclient/models/deployresult.py b/testapi/testapi-client/testapiclient/models/deployresult.py
new file mode 100644
index 0000000..5c13966
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/models/deployresult.py
@@ -0,0 +1,17 @@
+class DeployResultCreateRequest():
+ def __init__(
+ self, build_id='', scenario='', stop_date='', start_date='',
+ upstream_job_name='', version='', pod_name='', criteria='',
+ installer='', upstream_build_id='', job_name='', details=''):
+ self.build_id = build_id
+ self.scenario = scenario
+ self.stop_date = stop_date
+ self.start_date = start_date
+ self.upstream_job_name = upstream_job_name
+ self.version = version
+ self.pod_name = pod_name
+ self.criteria = criteria
+ self.installer = installer
+ self.upstream_build_id = upstream_build_id
+ self.job_name = job_name
+ self.details = details
diff --git a/testapi/testapi-client/testapiclient/models/pods.py b/testapi/testapi-client/testapiclient/models/pods.py
new file mode 100644
index 0000000..4fa42e7
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/models/pods.py
@@ -0,0 +1,6 @@
+class PodCreateRequest(object):
+ def __init__(self, name='', mode='', details='', role=''):
+ self.name = name
+ self.mode = mode
+ self.details = details
+ self.role = role
diff --git a/testapi/testapi-client/testapiclient/models/project.py b/testapi/testapi-client/testapiclient/models/project.py
new file mode 100644
index 0000000..fc85588
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/models/project.py
@@ -0,0 +1,4 @@
+class ProjectCreateRequest():
+ def __init__(self, name='', description=''):
+ self.description = description
+ self.name = name
diff --git a/testapi/testapi-client/testapiclient/models/result.py b/testapi/testapi-client/testapiclient/models/result.py
new file mode 100644
index 0000000..766c03a
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/models/result.py
@@ -0,0 +1,16 @@
+class ResultCreateRequest():
+ def __init__(
+ self, project_name='', scenario='', case_name='', pod_name='',
+ installer='', version='', stop_date='', build_tag='', criteria='',
+ start_date='', details=''):
+ self.project_name = project_name
+ self.scenario = scenario
+ self.case_name = case_name
+ self.pod_name = pod_name
+ self.installer = installer
+ self.version = version
+ self.stop_date = stop_date
+ self.build_tag = build_tag
+ self.criteria = criteria
+ self.start_date = start_date
+ self.details = details
diff --git a/testapi/testapi-client/testapiclient/models/scenario.py b/testapi/testapi-client/testapiclient/models/scenario.py
new file mode 100644
index 0000000..f4f0f40
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/models/scenario.py
@@ -0,0 +1,37 @@
+class ScenarioCreateRequest:
+ def __init__(self, name='', installers=[]):
+ self.name = name
+ self.installers = installers
+
+
+class ScenarioInstallerCreateRequest:
+ def __init__(self, installer='', versions=[]):
+ self.installer = installer
+ self.versions = versions
+
+
+class ScenarioVersionCreateRequest:
+ def __init__(self, version='', owner='', projects=[]):
+ self.version = version
+ self.owner = owner
+ self.projects = projects
+
+
+class ScenarioProjectCreateRequest:
+ def __init__(self, project='', scores=[], trust_indicators=[], customs=[]):
+ self.project = project
+ self.scores = scores
+ self.trust_indicators = trust_indicators
+ self.customs = customs
+
+
+class ScenarioScoreCreateRequest:
+ def __init__(self, score='', date=''):
+ self.score = score
+ self.date = date
+
+
+class ScenarioTICreateRequest:
+ def __init__(self, status='', date=''):
+ self.status = status
+ self.date = date
diff --git a/testapi/testapi-client/testapiclient/models/testcase.py b/testapi/testapi-client/testapiclient/models/testcase.py
new file mode 100644
index 0000000..70d5d78
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/models/testcase.py
@@ -0,0 +1,20 @@
+class TestCaseCreateRequest():
+ def __init__(
+ self, run='', name='', ci_loop='', tags='', url='',
+ blocking='', domains='', dependencies='', version='',
+ criteria='', tier='', trust='', catalog_description='',
+ description=''):
+ self.run = run
+ self.name = name
+ self.ci_loop = ci_loop
+ self.tags = tags
+ self.url = url
+ self.blocking = blocking
+ self.domains = domains
+ self.dependencies = dependencies
+ self.version = version
+ self.criteria = criteria
+ self.tier = tier
+ self.trust = trust
+ self.catalog_description = catalog_description
+ self.description = description
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_app.py b/testapi/testapi-client/testapiclient/tests/unit/test_app.py
new file mode 100644
index 0000000..c20b27f
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_app.py
@@ -0,0 +1,50 @@
+import urllib
+
+from mock import mock
+
+from testapiclient import main
+from testapiclient.tests.unit import utils
+from testapiclient.tests.unit import fakes
+
+
+class MainTest(utils.TestCommand):
+ def setUp(self):
+ super(MainTest, self).setUp()
+ self.app = main.TestAPIClient()
+ self.cas_sever = '{}{}{}'.format(
+ self.env_variables['testapi_cas_auth_url'],
+ urllib.quote(self.env_variables['testapi_url']),
+ self.env_variables['testapi_cas_signin_return'])
+ self.headers = {
+ 'Content-type': 'application/json',
+ 'Accept': 'text/plain'}
+
+ def test_auth_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(
+ data={'text': "success"})
+ self.app.run(
+ ['-u', 'user', '-p', 'pass', 'pod', 'create',
+ '{"name": "asfad"}'])
+ self.post_mock.assert_called_with(
+ 'http://localhost:8000/api/v1/pods',
+ data='{"name": "asfad"}',
+ headers=self.headers)
+
+ def test_auth_failure(self):
+ self.post_mock.return_value = fakes.FakeResponse(
+ data={'text': "login"})
+ self.app.run(
+ ['-u', 'user', '-p', 'pass', 'pod', 'create',
+ '{"name": "asfad"}'])
+ self.post_mock.assert_called_once_with(
+ self.cas_sever,
+ {'pass': 'pass', 'name': 'user', 'form_id': 'user_login'}
+ )
+
+ def test_auth_not_called(self):
+ self.auth_post = mock.patch(
+ 'testapiclient.utils.clientmanager.ClientManager.auth').start()
+ self.app.run(['pod', 'get'])
+ self.auth_post.assert_not_called()
+ self.get_mock.assert_called_once_with(
+ 'http://localhost:8000/api/v1/pods', headers=self.headers)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_deployresults_client.py b/testapi/testapi-client/testapiclient/tests/unit/test_deployresults_client.py
new file mode 100644
index 0000000..03288fe
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_deployresults_client.py
@@ -0,0 +1,81 @@
+import json
+
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.client import deploy_results
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+from testapiclient.utils import clientmanager
+
+
+class DeployResultsClientTest(utils.TestCommand):
+ def setUp(self):
+ super(DeployResultsClientTest, self).setUp()
+ self.base_url = parse.urljoin(self.api_url, 'deployresults')
+ self.deployresult_json = {
+ 'project_name': 'functest',
+ 'scenario': 'test-scenario',
+ 'stop_date': '2018-04-09 13:44:53',
+ 'case_name': 'test-case',
+ 'build_tag': 'test-build',
+ 'version': 'test-version',
+ 'pod_name': 'test-pod',
+ 'criteria': 'test-criteria',
+ 'installer': 'test-installer',
+ 'start_date': '2018-04-09 13:44:53',
+ 'details': 'test-details'
+ }
+ self.deployresult_id = '5a6dc1089a07c80f3c9f8d62'
+ self.deployresult_string = json.dumps(self.deployresult_json)
+ self.deployresult_client = deploy_results.DeployResultsClient()
+
+
+class DeployResultsClientGetTest(DeployResultsClientTest):
+
+ def setUp(self):
+ super(DeployResultsClientGetTest, self).setUp()
+ self.deployresults_rsp = {'deployresults': [self.deployresult_json]}
+
+ def test_get(self):
+ self.get_mock.return_value = fakes.FakeResponse(
+ data=self.deployresults_rsp)
+ self.deployresult_client.get()
+ self.get_mock.assert_called_once_with(
+ self.base_url,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_get_search(self):
+ self.get_mock.return_value = fakes.FakeResponse(
+ data=self.deployresults_rsp)
+ self.deployresult_client.get(name='deployresult1')
+ self.get_mock.assert_called_once_with(
+ self.base_url + '?name=deployresult1',
+ headers=clientmanager.ClientManager.headers)
+
+ def test_get_one(self):
+ self.get_mock.return_value = fakes.FakeResponse(
+ data=self.deployresult_json)
+ self.deployresult_client.get_one('2333')
+ self.get_mock.assert_called_once_with(
+ self.base_url + '/2333',
+ headers=clientmanager.ClientManager.headers)
+
+
+class DeployResultsClientCreateTest(DeployResultsClientTest):
+
+ def setUp(self):
+ super(DeployResultsClientCreateTest, self).setUp()
+ self.succ_rsp = {
+ 'href': '{}/{}'.format(self.base_url, self.deployresult_id)
+ }
+
+ def test_create_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(data=self.succ_rsp)
+ self.deployresult_client.create(self.deployresult_json)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ self.deployresult_client.create(self.deployresult_json)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_pod_client.py b/testapi/testapi-client/testapiclient/tests/unit/test_pod_client.py
new file mode 100644
index 0000000..1df5660
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_pod_client.py
@@ -0,0 +1,89 @@
+import json
+
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.client import pods
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+from testapiclient.utils import clientmanager
+
+
+class PodClientTest(utils.TestCommand):
+ def setUp(self):
+ super(PodClientTest, self).setUp()
+ self.base_url = parse.urljoin(self.api_url, 'pods')
+ self.pod_json = {
+ 'role': 'community-ci',
+ 'name': 'test_pod',
+ 'details': '',
+ 'mode': 'metal'
+ }
+ self.pod_client = pods.PodsClient()
+ self.pod_string = json.dumps(self.pod_json)
+
+
+class PodClientGetTest(PodClientTest):
+
+ def setUp(self):
+ super(PodClientGetTest, self).setUp()
+ self.pods_rsp = {'pods': [self.pod_json]}
+
+ def test_get(self):
+ self.get_mock.return_value = fakes.FakeResponse(data=self.pods_rsp)
+ self.pod_client.get()
+ self.get_mock.assert_called_once_with(
+ self.base_url,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_get_search(self):
+ self.get_mock.return_value = fakes.FakeResponse(data=self.pods_rsp)
+ self.pod_client.get(name='pod1')
+ self.get_mock.assert_called_once_with(
+ self.base_url + '?name=pod1',
+ headers=clientmanager.ClientManager.headers)
+
+ def test_get_one(self):
+ self.get_mock.return_value = fakes.FakeResponse(data=self.pod_json)
+ self.pod_client.get_one('def')
+ self.get_mock.assert_called_once_with(
+ self.base_url + '/def',
+ headers=clientmanager.ClientManager.headers)
+
+
+class PodClientCreateTest(PodClientTest):
+
+ def setUp(self):
+ super(PodClientCreateTest, self).setUp()
+ self.succ_rsp = {
+ 'href': '{}/{}'.format(self.base_url, self.pod_json.get('name'))
+ }
+
+ def test_create_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(data=self.succ_rsp)
+ self.pod_client.create(self.pod_json)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ self.pod_client.create(self.pod_json)
+
+
+class PodClientDeleteTest(PodClientTest):
+
+ def setUp(self):
+ super(PodClientDeleteTest, self).setUp()
+
+ def test_delete_success(self):
+ self.delete_mock.return_value = fakes.FakeResponse()
+ self.pod_client.delete('def')
+ self.delete_mock.assert_called_once_with(
+ self.base_url + '/def',
+ data=None,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_delete_failure(self):
+ with testtools.ExpectedException(Exception, 'Delete failed: Error'):
+ self.delete_mock.return_value = utils.FAKE_FAILURE
+ self.pod_client.delete('def')
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_project_client.py b/testapi/testapi-client/testapiclient/tests/unit/test_project_client.py
new file mode 100644
index 0000000..7aa11e6
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_project_client.py
@@ -0,0 +1,111 @@
+import json
+
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.client import projects
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+from testapiclient.utils import clientmanager
+
+
+class ProjectClientTest(utils.TestCommand):
+ def setUp(self):
+ super(ProjectClientTest, self).setUp()
+ self.base_url = parse.urljoin(self.api_url, 'projects')
+ self.project_json = {
+ 'description': 'test_description',
+ 'name': 'test_project',
+ }
+ self.project_client = projects.ProjectsClient()
+ self.project_string = json.dumps(self.project_json)
+
+
+class ProjectClientGetTest(ProjectClientTest):
+
+ def setUp(self):
+ super(ProjectClientGetTest, self).setUp()
+ self.projects_rsp = {'projects': [self.project_json]}
+
+ def test_get(self):
+ self.get_mock.return_value = fakes.FakeResponse(
+ data=self.projects_rsp)
+ self.project_client.get()
+ self.get_mock.assert_called_once_with(
+ self.base_url,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_get_search(self):
+ self.get_mock.return_value = fakes.FakeResponse(
+ data=self.projects_rsp)
+ self.project_client.get(name='project1')
+ self.get_mock.assert_called_once_with(
+ self.base_url + '?name=project1',
+ headers=clientmanager.ClientManager.headers)
+
+ def test_get_one(self):
+ self.get_mock.return_value = fakes.FakeResponse(
+ data=self.project_json)
+ self.project_client.get_one('def')
+ self.get_mock.assert_called_once_with(
+ self.base_url + '/def',
+ headers=clientmanager.ClientManager.headers)
+
+
+class ProjectClientCreateTest(ProjectClientTest):
+
+ def setUp(self):
+ super(ProjectClientCreateTest, self).setUp()
+ self.succ_rsp = {
+ 'href': '{}/{}'.format(
+ self.base_url, self.project_json.get('name'))
+ }
+
+ def test_create_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(
+ data=self.succ_rsp)
+ self.project_client.create(self.project_json)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ self.project_client.create(self.project_json)
+
+
+class ProjectClientDeleteTest(ProjectClientTest):
+
+ def setUp(self):
+ super(ProjectClientDeleteTest, self).setUp()
+
+ def test_delete_success(self):
+ self.delete_mock.return_value = fakes.FakeResponse()
+ self.project_client.delete('def')
+ self.delete_mock.assert_called_once_with(
+ self.base_url + '/def',
+ data=None,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_delete_failure(self):
+ with testtools.ExpectedException(Exception, 'Delete failed: Error'):
+ self.delete_mock.return_value = utils.FAKE_FAILURE
+ self.project_client.delete('def')
+
+
+class ProjectClientUpdateTest(ProjectClientTest):
+
+ def setUp(self):
+ super(ProjectClientUpdateTest, self).setUp()
+
+ def test_update_success(self):
+ self.put_mock.return_value = fakes.FakeResponse()
+ self.project_client.update('def', self.project_json)
+ self.put_mock.assert_called_once_with(
+ self.base_url + '/def',
+ data=self.project_string,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_update_failure(self):
+ with testtools.ExpectedException(Exception, 'Update failed: Error'):
+ self.put_mock.return_value = utils.FAKE_FAILURE
+ self.project_client.update('def', self.project_json)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_results.py b/testapi/testapi-client/testapiclient/tests/unit/test_results.py
new file mode 100644
index 0000000..83bcc9f
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_results.py
@@ -0,0 +1,98 @@
+import json
+
+from mock import mock
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.cli import results
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+from testapiclient.utils import clientmanager
+
+
+class ResultTest(utils.TestCommand):
+ def setUp(self):
+ super(ResultTest, self).setUp()
+ self.base_url = parse.urljoin(self.api_url, 'results')
+ self.result_json = {
+ 'project_name': 'functest',
+ 'scenario': 'test-scenario',
+ 'stop_date': '2018-04-09 13:44:53',
+ 'case_name': 'test-case',
+ 'build_tag': 'test-build',
+ 'version': 'test-version',
+ 'pod_name': 'test-pod',
+ 'criteria': 'test-criteria',
+ 'installer': 'test-installer',
+ 'start_date': '2018-04-09 13:44:53',
+ 'details': 'test-details'
+ }
+ self.result_string = json.dumps(self.result_json)
+
+
+class ResultGetTest(ResultTest):
+
+ def setUp(self):
+ super(ResultGetTest, self).setUp()
+ self.results_rsp = {'results': [self.result_json]}
+
+ def test_get(self):
+ self.get_mock.return_value = fakes.FakeResponse(data=self.results_rsp)
+ result_get = results.ResultGet(self.app, mock.Mock())
+ args = ['-case', 'dfs']
+ verifies = [('case', 'dfs')]
+ parsed_args = self.check_parser(result_get, args, verifies)
+ result_get.take_action(parsed_args)
+ self.get_mock.assert_called_once_with(
+ self.base_url + '?case=dfs',
+ headers=clientmanager.ClientManager.headers)
+
+ def test_get_all(self):
+ self.get_mock.return_value = fakes.FakeResponse(data=self.results_rsp)
+ result_get = results.ResultGet(self.app, mock.Mock())
+ args = []
+ verifies = []
+ parsed_args = self.check_parser(result_get, args, verifies)
+ result_get.take_action(parsed_args)
+ self.get_mock.assert_called_once_with(
+ self.base_url,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_get_one(self):
+ self.get_mock.return_value = fakes.FakeResponse(data=self.result_json)
+ result_get_one = results.ResultGetOne(self.app, mock.Mock())
+ args = ['def']
+ verifies = [('result_id', 'def')]
+ parsed_args = self.check_parser(result_get_one, args, verifies)
+ result_get_one.take_action(parsed_args)
+ self.get_mock.assert_called_once_with(
+ self.base_url + '/def',
+ headers=clientmanager.ClientManager.headers)
+
+
+class ResultCreateTest(ResultTest):
+
+ def setUp(self):
+ super(ResultCreateTest, self).setUp()
+
+ def test_create_success(self):
+ succ_rsp = {
+ 'href': '{}/{}'.format(self.base_url,
+ self.result_json.get('project_name'))
+ }
+ self.post_mock.return_value = fakes.FakeResponse(data=succ_rsp)
+ result_create = results.ResultCreate(self.app, mock.Mock())
+ args = [self.result_string]
+ verifies = [('result', self.result_json)]
+ parsed_args = self.check_parser(result_create, args, verifies)
+ result_create.take_action(parsed_args)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ result_create = results.ResultCreate(self.app, mock.Mock())
+ args = [self.result_string]
+ verifies = [('result', self.result_json)]
+ parsed_args = self.check_parser(result_create, args, verifies)
+ result_create.take_action(parsed_args)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_results_client.py b/testapi/testapi-client/testapiclient/tests/unit/test_results_client.py
new file mode 100644
index 0000000..ae677f7
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_results_client.py
@@ -0,0 +1,78 @@
+import json
+
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.client import results
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+from testapiclient.utils import clientmanager
+
+
+class ResultClientTest(utils.TestCommand):
+ def setUp(self):
+ super(ResultClientTest, self).setUp()
+ self.base_url = parse.urljoin(self.api_url, 'results')
+ self.result_json = {
+ 'project_name': 'functest',
+ 'scenario': 'test-scenario',
+ 'stop_date': '2018-04-09 13:44:53',
+ 'case_name': 'test-case',
+ 'build_tag': 'test-build',
+ 'version': 'test-version',
+ 'pod_name': 'test-pod',
+ 'criteria': 'test-criteria',
+ 'installer': 'test-installer',
+ 'start_date': '2018-04-09 13:44:53',
+ 'details': 'test-details'
+ }
+ self.result_id = '5a6dc1089a07c80f3c9f8d62'
+ self.result_string = json.dumps(self.result_json)
+ self.result_client = results.ResultsClient()
+
+
+class ResultClientGetTest(ResultClientTest):
+
+ def setUp(self):
+ super(ResultClientGetTest, self).setUp()
+ self.results_rsp = {'results': [self.result_json]}
+
+ def test_get(self):
+ self.get_mock.return_value = fakes.FakeResponse(data=self.results_rsp)
+ self.result_client.get()
+ self.get_mock.assert_called_once_with(
+ self.base_url,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_get_search(self):
+ self.get_mock.return_value = fakes.FakeResponse(data=self.results_rsp)
+ self.result_client.get(name='result1')
+ self.get_mock.assert_called_once_with(
+ self.base_url + '?name=result1',
+ headers=clientmanager.ClientManager.headers)
+
+ def test_get_one(self):
+ self.get_mock.return_value = fakes.FakeResponse(data=self.result_json)
+ self.result_client.get_one('2333')
+ self.get_mock.assert_called_once_with(
+ self.base_url + '/2333',
+ headers=clientmanager.ClientManager.headers)
+
+
+class ResultClientCreateTest(ResultClientTest):
+
+ def setUp(self):
+ super(ResultClientCreateTest, self).setUp()
+ self.succ_rsp = {
+ 'href': '{}/{}'.format(self.base_url, self.result_id)
+ }
+
+ def test_create_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(data=self.succ_rsp)
+ self.result_client.create(self.result_json)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ self.result_client.create(self.result_json)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_scenario_client.py b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_client.py
new file mode 100644
index 0000000..6e9e0fa
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_client.py
@@ -0,0 +1,104 @@
+import json
+
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.client import scenarios
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+from testapiclient.utils import clientmanager
+
+
+class ScenarioClientTest(utils.TestCommand):
+ def setUp(self):
+ super(ScenarioClientTest, self).setUp()
+ self.base_url = parse.urljoin(self.api_url, 'scenarios')
+ self.scenario_json = {
+ "installers": [],
+ "name": "test_scenario"
+ }
+ self.scenario_client = scenarios.ScenariosClient()
+ self.scenario_string = json.dumps(self.scenario_json)
+
+
+class ScenarioClientGetTest(ScenarioClientTest):
+
+ def setUp(self):
+ super(ScenarioClientGetTest, self).setUp()
+ self.scenarios_rsp = {'scenarios': [self.scenario_json]}
+
+ def test_get(self):
+ self.get_mock.return_value = fakes.FakeResponse(
+ data=self.scenarios_rsp)
+ self.scenario_client.get()
+ self.get_mock.assert_called_once_with(
+ self.base_url,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_get_one(self):
+ self.get_mock.return_value = fakes.FakeResponse(
+ data=self.scenario_json)
+ self.scenario_client.get_one('def')
+ self.get_mock.assert_called_once_with(
+ self.base_url + '/def',
+ headers=clientmanager.ClientManager.headers)
+
+
+class ScenarioClientCreateTest(ScenarioClientTest):
+
+ def setUp(self):
+ super(ScenarioClientCreateTest, self).setUp()
+ self.succ_rsp = {
+ 'href': '{}/{}'.format(
+ self.base_url, self.scenario_json.get('name'))
+ }
+
+ def test_create_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(
+ data=self.succ_rsp)
+ self.scenario_client.create(self.scenario_json)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ self.scenario_client.create(self.scenario_json)
+
+
+class ScenarioClientDeleteTest(ScenarioClientTest):
+
+ def setUp(self):
+ super(ScenarioClientDeleteTest, self).setUp()
+
+ def test_delete_success(self):
+ self.delete_mock.return_value = fakes.FakeResponse()
+ self.scenario_client.delete('def')
+ self.delete_mock.assert_called_once_with(
+ self.base_url + '/def',
+ data=None,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_delete_failure(self):
+ with testtools.ExpectedException(Exception, 'Delete failed: Error'):
+ self.delete_mock.return_value = utils.FAKE_FAILURE
+ self.scenario_client.delete('def')
+
+
+class ScenarioClientUpdateTest(ScenarioClientTest):
+
+ def setUp(self):
+ super(ScenarioClientUpdateTest, self).setUp()
+
+ def test_update_success(self):
+ self.put_mock.return_value = fakes.FakeResponse()
+ self.scenario_client.update(
+ 'def', self.scenario_json)
+ self.put_mock.assert_called_once_with(
+ self.base_url + '/def',
+ data=self.scenario_string,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_update_failure(self):
+ with testtools.ExpectedException(Exception, 'Update failed: Error'):
+ self.put_mock.return_value = utils.FAKE_FAILURE
+ self.scenario_client.update('def', self.scenario_json)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_scenario_custom_client.py b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_custom_client.py
new file mode 100644
index 0000000..7c6d62c
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_custom_client.py
@@ -0,0 +1,106 @@
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.client import scenarios
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+
+
+class CustomClientTest(utils.TestCommand):
+ def setUp(self):
+ super(CustomClientTest, self).setUp()
+ self.scenario_name = 'scenrio1'
+ self.base_url = parse.urljoin(
+ self.api_url,
+ 'scenarios/{}/customs'.format(self.scenario_name))
+ self.custom_raw = 'custom'
+ self.custom_input = ['custom']
+ self.installer_name = 'installer'
+ self.version_name = 'version'
+ self.project_name = 'project'
+ self.custom_client = scenarios.CustomsClient()
+
+
+class CustomClientCreateTest(CustomClientTest):
+
+ def setUp(self):
+ super(CustomClientCreateTest, self).setUp()
+ self.succ_rsp = {
+ 'href': '{}/{}'.format(
+ self.base_url, self.scenario_name)
+ }
+
+ def test_create_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(
+ data=self.succ_rsp)
+ self.custom_client.create(
+ self.scenario_name, self.installer_name,
+ self.version_name, self.project_name,
+ self.custom_raw)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ self.custom_client.create(
+ self.scenario_name, self.installer_name,
+ self.version_name, self.project_name,
+ self.custom_raw)
+
+
+class CustomClientDeleteTest(CustomClientTest):
+
+ def setUp(self):
+ super(CustomClientDeleteTest, self).setUp()
+
+ def test_delete_success(self):
+ self.delete_mock.return_value = fakes.FakeResponse()
+ self.custom_client.delete(
+ self.scenario_name, self.installer_name,
+ self.version_name, self.project_name,
+ self.custom_raw)
+ kall = self.delete_mock.call_args
+ args, kwargs = kall
+ self.assert_url(
+ args[0],
+ self.base_url +
+ '?installer=installer&version=version&project=project')
+
+ def test_delete_failure(self):
+ with testtools.ExpectedException(Exception, 'Delete failed: Error'):
+ self.delete_mock.return_value = utils.FAKE_FAILURE
+ self.custom_client.delete(
+ self.scenario_name, self.installer_name,
+ self.version_name, self.project_name,
+ self.custom_raw)
+
+
+class CustomClientUpdateTest(CustomClientTest):
+
+ def setUp(self):
+ super(CustomClientUpdateTest, self).setUp()
+
+ def test_update_success(self):
+ self.put_mock.return_value = fakes.FakeResponse()
+ self.custom_client.update(
+ self.scenario_name,
+ self.installer_name,
+ self.version_name,
+ self.project_name,
+ self.custom_raw)
+ kall = self.put_mock.call_args
+ args, kwargs = kall
+ self.assert_url(
+ args[0],
+ self.base_url +
+ '?installer=installer&version=version&project=project')
+
+ def test_update_failure(self):
+ with testtools.ExpectedException(Exception, 'Update failed: Error'):
+ self.put_mock.return_value = utils.FAKE_FAILURE
+ self.custom_client.update(
+ self.scenario_name,
+ self.installer_name,
+ self.version_name,
+ self.project_name,
+ self.custom_raw)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_scenario_installer_client.py b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_installer_client.py
new file mode 100644
index 0000000..71ba150
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_installer_client.py
@@ -0,0 +1,86 @@
+import json
+
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.client import scenarios
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+from testapiclient.utils import clientmanager
+
+
+class InstallerClientTest(utils.TestCommand):
+ def setUp(self):
+ super(InstallerClientTest, self).setUp()
+ self.scenario_name = 'scenrio1'
+ self.base_url = parse.urljoin(
+ self.api_url,
+ 'scenarios/{}/installers'.format(self.scenario_name))
+ self.installer_json = {
+ 'versions': [],
+ 'installer': 'test-installer',
+ }
+ self.installer_client = scenarios.InstallersClient()
+ self.installer_string = json.dumps(self.installer_json)
+
+
+class InstallerClientCreateTest(InstallerClientTest):
+
+ def setUp(self):
+ super(InstallerClientCreateTest, self).setUp()
+ self.succ_rsp = {
+ 'href': '{}/{}'.format(
+ self.base_url, self.installer_json.get('name'))
+ }
+
+ def test_create_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(
+ data=self.succ_rsp)
+ self.installer_client.create(self.scenario_name, self.installer_json)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ self.installer_client.create(
+ self.scenario_name, self.installer_json)
+
+
+class InstallerClientDeleteTest(InstallerClientTest):
+
+ def setUp(self):
+ super(InstallerClientDeleteTest, self).setUp()
+
+ def test_delete_success(self):
+ self.delete_mock.return_value = fakes.FakeResponse()
+ self.installer_client.delete(self.scenario_name, 'def')
+ self.delete_mock.assert_called_once_with(
+ self.base_url,
+ data=json.dumps(['def']),
+ headers=clientmanager.ClientManager.headers)
+
+ def test_delete_failure(self):
+ with testtools.ExpectedException(Exception, 'Delete failed: Error'):
+ self.delete_mock.return_value = utils.FAKE_FAILURE
+ self.installer_client.delete(self.scenario_name, 'def')
+
+
+class InstallerClientUpdateTest(InstallerClientTest):
+
+ def setUp(self):
+ super(InstallerClientUpdateTest, self).setUp()
+
+ def test_update_success(self):
+ self.put_mock.return_value = fakes.FakeResponse()
+ self.installer_client.update(
+ self.scenario_name,
+ self.installer_json)
+ self.put_mock.assert_called_once_with(
+ self.base_url,
+ data=self.installer_string,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_update_failure(self):
+ with testtools.ExpectedException(Exception, 'Update failed: Error'):
+ self.put_mock.return_value = utils.FAKE_FAILURE
+ self.installer_client.update('def', self.installer_json)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_scenario_project_client.py b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_project_client.py
new file mode 100644
index 0000000..f8c3d60
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_project_client.py
@@ -0,0 +1,104 @@
+import json
+
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.client import scenarios
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+
+
+class ProjectClientTest(utils.TestCommand):
+ def setUp(self):
+ super(ProjectClientTest, self).setUp()
+ self.scenario_name = 'scenrio1'
+ self.base_url = parse.urljoin(
+ self.api_url,
+ 'scenarios/{}/projects'.format(self.scenario_name))
+ self.project_json = {
+ 'trust_indicators': [],
+ 'project': 'test-project',
+ 'scores': [],
+ 'customs': []
+ }
+ self.installer_name = 'installer'
+ self.version_name = 'version'
+ self.project_client = scenarios.ProjectsClient()
+ self.project_string = json.dumps(self.project_json)
+
+
+class ProjectClientCreateTest(ProjectClientTest):
+
+ def setUp(self):
+ super(ProjectClientCreateTest, self).setUp()
+ self.succ_rsp = {
+ 'href': '{}/{}'.format(
+ self.base_url, self.project_json.get('name'))
+ }
+
+ def test_create_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(
+ data=self.succ_rsp)
+ self.project_client.create(
+ self.scenario_name, self.installer_name,
+ self.version_name, self.project_json)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ self.project_client.create(
+ self.scenario_name, self.installer_name,
+ self.version_name, self.project_json)
+
+
+class ProjectClientDeleteTest(ProjectClientTest):
+
+ def setUp(self):
+ super(ProjectClientDeleteTest, self).setUp()
+
+ def test_delete_success(self):
+ self.delete_mock.return_value = fakes.FakeResponse()
+ self.project_client.delete(
+ self.scenario_name, self.installer_name,
+ self.version_name, 'def')
+ kall = self.delete_mock.call_args
+ args, kwargs = kall
+ self.assert_url(
+ args[0],
+ self.base_url + '?installer=installer&version=version')
+
+ def test_delete_failure(self):
+ with testtools.ExpectedException(Exception, 'Delete failed: Error'):
+ self.delete_mock.return_value = utils.FAKE_FAILURE
+ self.project_client.delete(
+ self.scenario_name, self.installer_name,
+ self.version_name, 'def')
+
+
+class ProjectClientUpdateTest(ProjectClientTest):
+
+ def setUp(self):
+ super(ProjectClientUpdateTest, self).setUp()
+
+ def test_update_success(self):
+ self.put_mock.return_value = fakes.FakeResponse()
+ self.project_client.update(
+ self.scenario_name,
+ self.installer_name,
+ self.version_name,
+ self.project_json)
+ kall = self.put_mock.call_args
+ args, kwargs = kall
+ self.assert_url(
+ args[0],
+ self.base_url + '?installer=installer&version=version')
+
+ def test_update_failure(self):
+ with testtools.ExpectedException(Exception, 'Update failed: Error'):
+ self.put_mock.return_value = utils.FAKE_FAILURE
+ self.project_client.update(
+ self.scenario_name,
+ self.installer_name,
+ self.version_name,
+ self.project_json)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_scenario_score_client.py b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_score_client.py
new file mode 100644
index 0000000..beebd47
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_score_client.py
@@ -0,0 +1,53 @@
+import json
+
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.client import scenarios
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+
+
+class ScoreClientTest(utils.TestCommand):
+ def setUp(self):
+ super(ScoreClientTest, self).setUp()
+ self.scenario_name = 'scenrio1'
+ self.base_url = parse.urljoin(
+ self.api_url,
+ 'scenarios/{}/scores'.format(self.scenario_name))
+ self.score_json = {
+ 'score': 'test_score1',
+ 'date': '2018/01/2'
+ }
+ self.installer_name = 'installer'
+ self.version_name = 'version'
+ self.project_name = 'project'
+ self.score_client = scenarios.ScoresClient()
+ self.score_string = json.dumps(self.score_json)
+
+
+class ScoreClientCreateTest(ScoreClientTest):
+
+ def setUp(self):
+ super(ScoreClientCreateTest, self).setUp()
+ self.succ_rsp = {
+ 'href': '{}/{}'.format(
+ self.base_url, self.score_json.get('name'))
+ }
+
+ def test_create_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(
+ data=self.succ_rsp)
+ self.score_client.create(
+ self.scenario_name, self.installer_name,
+ self.version_name, self.project_name,
+ self.score_json)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ self.score_client.create(
+ self.scenario_name, self.installer_name,
+ self.version_name, self.project_name,
+ self.score_json)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_scenario_trust_indicator_client.py b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_trust_indicator_client.py
new file mode 100644
index 0000000..e44e2d2
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_trust_indicator_client.py
@@ -0,0 +1,53 @@
+import json
+
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.client import scenarios
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+
+
+class TrustIndicatorClientTest(utils.TestCommand):
+ def setUp(self):
+ super(TrustIndicatorClientTest, self).setUp()
+ self.scenario_name = 'scenrio1'
+ self.base_url = parse.urljoin(
+ self.api_url,
+ 'scenarios/{}/trust_indicators'.format(self.scenario_name))
+ self.trust_indicator_json = {
+ 'status': 'test_status',
+ 'date': '2018/01/2'
+ }
+ self.installer_name = 'installer'
+ self.version_name = 'version'
+ self.project_name = 'project'
+ self.trust_indicator_client = scenarios.TrustIndicatorsClient()
+ self.trust_indicator_string = json.dumps(self.trust_indicator_json)
+
+
+class TrustIndicatorClientCreateTest(TrustIndicatorClientTest):
+
+ def setUp(self):
+ super(TrustIndicatorClientCreateTest, self).setUp()
+ self.succ_rsp = {
+ 'href': '{}/{}'.format(
+ self.base_url, self.trust_indicator_json.get('name'))
+ }
+
+ def test_create_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(
+ data=self.succ_rsp)
+ self.trust_indicator_client.create(
+ self.scenario_name, self.installer_name,
+ self.version_name, self.project_name,
+ self.trust_indicator_json)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ self.trust_indicator_client.create(
+ self.scenario_name, self.installer_name,
+ self.version_name, self.project_name,
+ self.trust_indicator_json)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_scenario_version_client.py b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_version_client.py
new file mode 100644
index 0000000..1ae2409
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_scenario_version_client.py
@@ -0,0 +1,96 @@
+import json
+
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.client import scenarios
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+from testapiclient.utils import clientmanager
+
+
+class VersionClientTest(utils.TestCommand):
+ def setUp(self):
+ super(VersionClientTest, self).setUp()
+ self.scenario_name = 'scenrio1'
+ self.base_url = parse.urljoin(
+ self.api_url,
+ 'scenarios/{}/versions'.format(self.scenario_name))
+ self.version_json = {
+ 'projects': [],
+ 'version': 'test-version',
+ 'owner': 'test_owner'
+ }
+ self.installer_name = 'installer'
+ self.version_client = scenarios.VersionsClient()
+ self.version_string = json.dumps(self.version_json)
+
+
+class VersionClientCreateTest(VersionClientTest):
+
+ def setUp(self):
+ super(VersionClientCreateTest, self).setUp()
+ self.succ_rsp = {
+ 'href': '{}/{}'.format(
+ self.base_url, self.version_json.get('name'))
+ }
+
+ def test_create_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(
+ data=self.succ_rsp)
+ self.version_client.create(
+ self.scenario_name, self.installer_name, self.version_json)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ self.version_client.create(
+ self.scenario_name, self.installer_name, self.version_json)
+
+
+class VersionClientDeleteTest(VersionClientTest):
+
+ def setUp(self):
+ super(VersionClientDeleteTest, self).setUp()
+
+ def test_delete_success(self):
+ self.delete_mock.return_value = fakes.FakeResponse()
+ self.version_client.delete(
+ self.scenario_name, self.installer_name, 'def')
+ kall = self.delete_mock.call_args
+ args, kwargs = kall
+ self.assert_url(
+ args[0],
+ self.base_url + '?installer=installer')
+
+ def test_delete_failure(self):
+ with testtools.ExpectedException(Exception, 'Delete failed: Error'):
+ self.delete_mock.return_value = utils.FAKE_FAILURE
+ self.version_client.delete(
+ self.scenario_name, self.installer_name, 'def')
+
+
+class VersionClientUpdateTest(VersionClientTest):
+
+ def setUp(self):
+ super(VersionClientUpdateTest, self).setUp()
+
+ def test_update_success(self):
+ self.put_mock.return_value = fakes.FakeResponse()
+ self.version_client.update(
+ self.scenario_name,
+ self.installer_name,
+ self.version_json)
+ self.put_mock.assert_called_once_with(
+ self.base_url + '?installer=installer',
+ data=self.version_string,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_update_failure(self):
+ with testtools.ExpectedException(Exception, 'Update failed: Error'):
+ self.put_mock.return_value = utils.FAKE_FAILURE
+ self.version_client.update(
+ self.scenario_name,
+ self.installer_name,
+ self.version_json)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_testcase_client.py b/testapi/testapi-client/testapiclient/tests/unit/test_testcase_client.py
new file mode 100644
index 0000000..d80ae27
--- /dev/null
+++ b/testapi/testapi-client/testapiclient/tests/unit/test_testcase_client.py
@@ -0,0 +1,118 @@
+import json
+
+from six.moves.urllib import parse
+import testtools
+
+from testapiclient.client import testcases
+from testapiclient.tests.unit import fakes
+from testapiclient.tests.unit import utils
+from testapiclient.utils import clientmanager
+
+
+class TestcaseClientTest(utils.TestCommand):
+ def setUp(self):
+ super(TestcaseClientTest, self).setUp()
+ self.base_url = parse.urljoin(self.api_url, 'projects/{}/cases')
+ self.project_name = 'functest'
+ self.testcase_json = {
+ 'run': '',
+ 'name': 'test-case',
+ 'ci_loop': '',
+ 'tags': '',
+ 'url': '',
+ 'blocking': '',
+ 'domains': '',
+ 'dependencies': '',
+ 'version': '',
+ 'criteria': '',
+ 'tier': '',
+ 'trust': '',
+ 'catalog_description': '',
+ 'description': ''
+ }
+ self.testcase_client = testcases.TestcasesClient()
+ self.testcase_string = json.dumps(self.testcase_json)
+
+
+class TestcaseClientGetTest(TestcaseClientTest):
+
+ def setUp(self):
+ super(TestcaseClientGetTest, self).setUp()
+ self.testcases_rsp = {'testcases': [self.testcase_json]}
+
+ def test_get(self):
+ self.get_mock.return_value = fakes.FakeResponse(
+ data=self.testcases_rsp)
+ self.testcase_client.get(self.project_name)
+ self.get_mock.assert_called_once_with(
+ self.base_url.format(self.project_name),
+ headers=clientmanager.ClientManager.headers)
+
+ def test_get_one(self):
+ self.get_mock.return_value = fakes.FakeResponse(
+ data=self.testcase_json)
+ self.testcase_client.get_one(self.project_name, 'def')
+ self.get_mock.assert_called_once_with(
+ self.base_url.format(self.project_name) + '/def',
+ headers=clientmanager.ClientManager.headers)
+
+
+class TestcaseClientCreateTest(TestcaseClientTest):
+
+ def setUp(self):
+ super(TestcaseClientCreateTest, self).setUp()
+ self.succ_rsp = {
+ 'href': '{}/{}'.format(
+ self.base_url, self.testcase_json.get('name'))
+ }
+
+ def test_create_success(self):
+ self.post_mock.return_value = fakes.FakeResponse(
+ data=self.succ_rsp)
+ self.testcase_client.create(self.project_name, self.testcase_json)
+ self.post_mock.assert_called_once()
+
+ def test_create_failure(self):
+ with testtools.ExpectedException(Exception, 'Create failed: Error'):
+ self.post_mock.return_value = utils.FAKE_FAILURE
+ self.testcase_client.create(self.project_name, self.testcase_json)
+
+
+class TestcaseClientDeleteTest(TestcaseClientTest):
+
+ def setUp(self):
+ super(TestcaseClientDeleteTest, self).setUp()
+
+ def test_delete_success(self):
+ self.delete_mock.return_value = fakes.FakeResponse()
+ self.testcase_client.delete(self.project_name, 'def')
+ self.delete_mock.assert_called_once_with(
+ self.base_url.format(self.project_name) + '/def',
+ data=None,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_delete_failure(self):
+ with testtools.ExpectedException(Exception, 'Delete failed: Error'):
+ self.delete_mock.return_value = utils.FAKE_FAILURE
+ self.testcase_client.delete(self.project_name, 'def')
+
+
+class TestcaseClientUpdateTest(TestcaseClientTest):
+
+ def setUp(self):
+ super(TestcaseClientUpdateTest, self).setUp()
+
+ def test_update_success(self):
+ self.put_mock.return_value = fakes.FakeResponse()
+ self.testcase_client.update(
+ self.project_name, 'def', self.testcase_json)
+ self.put_mock.assert_called_once_with(
+ self.base_url.format(self.project_name) + '/def',
+ data=self.testcase_string,
+ headers=clientmanager.ClientManager.headers)
+
+ def test_update_failure(self):
+ with testtools.ExpectedException(Exception, 'Update failed: Error'):
+ self.put_mock.return_value = utils.FAKE_FAILURE
+ self.testcase_client.update(
+ self.project_name, 'def', self.testcase_json)
diff --git a/testapi/testapi-client/testapiclient/tests/unit/utils.py b/testapi/testapi-client/testapiclient/tests/unit/utils.py
index 21f98c4..c59aadd 100644
--- a/testapi/testapi-client/testapiclient/tests/unit/utils.py
+++ b/testapi/testapi-client/testapiclient/tests/unit/utils.py
@@ -19,7 +19,7 @@ class TestCommand(testtools.TestCase):
def setUp(self):
super(TestCommand, self).setUp()
- env_variables = {
+ self.env_variables = {
'testapi_url': 'http://localhost:8000/api/v1',
'testapi_cas_auth_url':
(
@@ -29,7 +29,7 @@ class TestCommand(testtools.TestCase):
'testapi_cas_signin_return': '/auth/signin_return'
}
self.config_mock = mock.patch.dict(
- 'os.environ', env_variables).start()
+ 'os.environ', self.env_variables).start()
self.fake_stdout = fakes.FakeStdout()
self.fake_log = fakes.FakeLog()
self.app = fakes.FakeApp(self.fake_stdout, self.fake_log)
diff --git a/testapi/testapi-client/testapiclient/utils/clientmanager.py b/testapi/testapi-client/testapiclient/utils/clientmanager.py
index 8858819..cbfd723 100644
--- a/testapi/testapi-client/testapiclient/utils/clientmanager.py
+++ b/testapi/testapi-client/testapiclient/utils/clientmanager.py
@@ -10,7 +10,9 @@ LOG = logging.getLogger(__name__)
class ClientManager(object):
- headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
+ headers = {
+ 'Content-type': 'application/json',
+ 'Accept': 'text/plain'}
def __init__(self, cli_options=None):
self.cli_options = cli_options
@@ -49,6 +51,8 @@ class ClientManager(object):
headers=self.headers))
def post(self, url, data):
+ if 'results' in url or 'deployresults' in url:
+ self.headers['X-Auth-Token'] = os.environ.get('testapi_token')
return self._parse_response('Create',
self._request('post', url,
data=json.dumps(data),