summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--reporting/reporting/bottlenecks/reporting-status.py6
-rw-r--r--testapi/3rd_party/static/testapi-ui/assets/css/style.css2
-rw-r--r--testapi/docker/Dockerfile2
-rw-r--r--testapi/docs/developer/devguide/images/CAS-sequence.jpgbin0 -> 11785 bytes
-rw-r--r--testapi/docs/developer/devguide/testapi-client-import.rst65
-rw-r--r--testapi/docs/developer/devguide/testapi-client.rst426
-rw-r--r--testapi/docs/developer/devguide/web-portal.rst114
-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/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/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/testapi-client/testapiclient/cli/pods.py7
-rw-r--r--testapi/testapi-client/testapiclient/cli/scenarios.py147
-rw-r--r--testapi/testapi-client/testapiclient/client/pods.py20
-rw-r--r--testapi/testapi-client/testapiclient/models/pods.py2
-rw-r--r--testapi/testapi-client/testapiclient/models/scenario.py37
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_app.py50
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_pod_client.py89
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/utils.py4
24 files changed, 1159 insertions, 207 deletions
diff --git a/reporting/reporting/bottlenecks/reporting-status.py b/reporting/reporting/bottlenecks/reporting-status.py
index 225227a..8966d06 100644
--- a/reporting/reporting/bottlenecks/reporting-status.py
+++ b/reporting/reporting/bottlenecks/reporting-status.py
@@ -37,14 +37,10 @@ for version in VERSIONS:
# For all the installers
for installer in INSTALLERS:
# get scenarios results data
- if version != 'master':
- new_version = "stable/{}".format(version)
- else:
- new_version = version
scenario_results = rp_utils.getScenarios("bottlenecks",
"posca_factor_ping",
installer,
- new_version)
+ version)
LOGGER.info("scenario_results: %s", scenario_results)
scenario_stats = rp_utils.getScenarioStats(scenario_results)
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 222911c..2b20d6b 100644
--- a/testapi/3rd_party/static/testapi-ui/assets/css/style.css
+++ b/testapi/3rd_party/static/testapi-ui/assets/css/style.css
@@ -303,7 +303,7 @@ json-tree .leaf-value{
border-radius: 10px;
padding: 16px;
position: fixed;
- z-index: 1;
+ z-index: 9999;
left: 50%;
bottom: 30px;
}
diff --git a/testapi/docker/Dockerfile b/testapi/docker/Dockerfile
index bbf12fc..86999d9 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
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..69cb6ad
--- /dev/null
+++ b/testapi/docs/developer/devguide/testapi-client-import.rst
@@ -0,0 +1,65 @@
+.. 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
+"""
+
+User will get the json Pod objects with the get request.
+
+.. code-block:: shell
+
+ from testapiclient.client import pods
+
+ pod_client = pods.PodsClient()
+ pod_client.get()
+
+User can use search parameters to get pods
+
+.. code-block:: shell
+
+ from testapiclient.client import pods
+
+ pod_client = pods.PodsClient()
+ pod_client.get(name='pod1')
+
+GET ONE
+"""""""
+
+User will get the json Pod objects with the get request.
+
+.. code-block:: shell
+
+ from testapiclient.client import pods
+
+ pod_client = pods.PodsClient()
+ pod_client.get_one('name')
+
+CREATE
+""""""
+User has to authenticate before running the function.
+
+.. 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':''}
+
diff --git a/testapi/docs/developer/devguide/testapi-client.rst b/testapi/docs/developer/devguide/testapi-client.rst
index ab4c8e8..ea08ad9 100644
--- a/testapi/docs/developer/devguide/testapi-client.rst
+++ b/testapi/docs/developer/devguide/testapi-client.rst
@@ -6,5 +6,427 @@
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": ""}'
+
+
+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.
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/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/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/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/testapi-client/testapiclient/cli/pods.py b/testapi/testapi-client/testapiclient/cli/pods.py
index df63737..a7706f6 100644
--- a/testapi/testapi-client/testapiclient/cli/pods.py
+++ b/testapi/testapi-client/testapiclient/cli/pods.py
@@ -3,6 +3,7 @@ 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():
@@ -61,8 +62,10 @@ 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
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/client/pods.py b/testapi/testapi-client/testapiclient/client/pods.py
index 4254da7..d08114f 100644
--- a/testapi/testapi-client/testapiclient/client/pods.py
+++ b/testapi/testapi-client/testapiclient/client/pods.py
@@ -1,4 +1,7 @@
+import json
+
from testapiclient.client import base
+from testapiclient.utils import urlparse
class PodsClient(base.Client):
@@ -9,3 +12,20 @@ class PodsClient(base.Client):
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/models/pods.py b/testapi/testapi-client/testapiclient/models/pods.py
index 27ea311..4fa42e7 100644
--- a/testapi/testapi-client/testapiclient/models/pods.py
+++ b/testapi/testapi-client/testapiclient/models/pods.py
@@ -1,5 +1,5 @@
class PodCreateRequest(object):
- def __init__(self, name='', mode='', details='', role=""):
+ def __init__(self, name='', mode='', details='', role=''):
self.name = name
self.mode = mode
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/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_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/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)