aboutsummaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/__init__.py38
-rw-r--r--services/__pycache__/__init__.cpython-36.pycbin0 -> 136 bytes
-rw-r--r--services/__pycache__/constants.cpython-36.pycbin0 -> 56696 bytes
-rw-r--r--services/__pycache__/helper.cpython-36.pycbin0 -> 6085 bytes
-rw-r--r--services/__pycache__/session.cpython-36.pycbin0 -> 2462 bytes
-rw-r--r--services/__pycache__/types.cpython-36.pycbin0 -> 2304 bytes
-rw-r--r--services/api/__init__.py38
-rw-r--r--services/api/__pycache__/__init__.cpython-36.pycbin0 -> 140 bytes
-rw-r--r--services/api/__pycache__/api_bridge.cpython-36.pycbin0 -> 1860 bytes
-rw-r--r--services/api/__pycache__/api_checklist.cpython-36.pycbin0 -> 5491 bytes
-rw-r--r--services/api/__pycache__/api_gitlab.cpython-36.pycbin0 -> 10952 bytes
-rw-r--r--services/api/__pycache__/api_jenkins.cpython-36.pycbin0 -> 1191 bytes
-rw-r--r--services/api/__pycache__/api_user.cpython-36.pycbin0 -> 7760 bytes
-rw-r--r--services/api/__pycache__/api_virtual_function.cpython-36.pycbin0 -> 9579 bytes
-rw-r--r--services/api/api_bridge.py74
-rw-r--r--services/api/api_checklist.py219
-rw-r--r--services/api/api_gitlab.py394
-rw-r--r--services/api/api_jenkins.py81
-rw-r--r--services/api/api_rados.py161
-rw-r--r--services/api/api_user.py308
-rw-r--r--services/api/api_virtual_function.py368
-rw-r--r--services/constants.py1036
-rw-r--r--services/database/__init__.py38
-rw-r--r--services/database/__pycache__/__init__.cpython-36.pycbin0 -> 145 bytes
-rw-r--r--services/database/__pycache__/db_bridge.cpython-36.pycbin0 -> 1251 bytes
-rw-r--r--services/database/__pycache__/db_checklist.cpython-36.pycbin0 -> 12128 bytes
-rw-r--r--services/database/__pycache__/db_cms.cpython-36.pycbin0 -> 8742 bytes
-rw-r--r--services/database/__pycache__/db_general.cpython-36.pycbin0 -> 10828 bytes
-rw-r--r--services/database/__pycache__/db_user.cpython-36.pycbin0 -> 11452 bytes
-rw-r--r--services/database/__pycache__/db_virtual_function.cpython-36.pycbin0 -> 8197 bytes
-rw-r--r--services/database/db_bridge.py60
-rw-r--r--services/database/db_checklist.py386
-rw-r--r--services/database/db_cms.py265
-rwxr-xr-xservices/database/db_general.py416
-rw-r--r--services/database/db_user.py417
-rw-r--r--services/database/db_virtual_function.py227
-rw-r--r--services/frontend/__init__.py38
-rw-r--r--services/frontend/__pycache__/__init__.cpython-36.pycbin0 -> 145 bytes
-rw-r--r--services/frontend/__pycache__/fe_checklist.cpython-36.pycbin0 -> 19862 bytes
-rw-r--r--services/frontend/__pycache__/fe_checklist_template.cpython-36.pycbin0 -> 7809 bytes
-rw-r--r--services/frontend/__pycache__/fe_cms.cpython-36.pycbin0 -> 5739 bytes
-rw-r--r--services/frontend/__pycache__/fe_dashboard.cpython-36.pycbin0 -> 8915 bytes
-rw-r--r--services/frontend/__pycache__/fe_detailed_view.cpython-36.pycbin0 -> 12656 bytes
-rw-r--r--services/frontend/__pycache__/fe_general.cpython-36.pycbin0 -> 7558 bytes
-rw-r--r--services/frontend/__pycache__/fe_invite.cpython-36.pycbin0 -> 5783 bytes
-rw-r--r--services/frontend/__pycache__/fe_overview.cpython-36.pycbin0 -> 14678 bytes
-rw-r--r--services/frontend/__pycache__/fe_user.cpython-36.pycbin0 -> 12392 bytes
-rwxr-xr-xservices/frontend/__pycache__/fe_wizard.cpython-36-PYTEST.pycbin0 -> 7434 bytes
-rw-r--r--services/frontend/__pycache__/fe_wizard.cpython-36.pycbin0 -> 6150 bytes
-rw-r--r--services/frontend/base_actions/__init__.py38
-rw-r--r--services/frontend/base_actions/__pycache__/__init__.cpython-36.pycbin0 -> 158 bytes
-rw-r--r--services/frontend/base_actions/__pycache__/click.cpython-36.pycbin0 -> 2607 bytes
-rw-r--r--services/frontend/base_actions/__pycache__/enter.cpython-36.pycbin0 -> 3741 bytes
-rw-r--r--services/frontend/base_actions/__pycache__/get.cpython-36.pycbin0 -> 3014 bytes
-rw-r--r--services/frontend/base_actions/__pycache__/wait.cpython-36.pycbin0 -> 6396 bytes
-rw-r--r--services/frontend/base_actions/click.py108
-rw-r--r--services/frontend/base_actions/enter.py139
-rw-r--r--services/frontend/base_actions/get.py127
-rw-r--r--services/frontend/base_actions/wait.py317
-rw-r--r--services/frontend/fe_checklist.py755
-rw-r--r--services/frontend/fe_checklist_template.py254
-rw-r--r--services/frontend/fe_cms.py157
-rw-r--r--services/frontend/fe_dashboard.py289
-rw-r--r--services/frontend/fe_detailed_view.py359
-rw-r--r--services/frontend/fe_general.py261
-rw-r--r--services/frontend/fe_invite.py198
-rw-r--r--services/frontend/fe_next_step.py56
-rw-r--r--services/frontend/fe_overview.py427
-rw-r--r--services/frontend/fe_user.py403
-rw-r--r--services/frontend/fe_wizard.py216
-rw-r--r--services/helper.py210
-rw-r--r--services/logging_service.py20
-rw-r--r--services/session.py106
-rw-r--r--services/types.py91
74 files changed, 9095 insertions, 0 deletions
diff --git a/services/__init__.py b/services/__init__.py
new file mode 100644
index 0000000..30d7152
--- /dev/null
+++ b/services/__init__.py
@@ -0,0 +1,38 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
diff --git a/services/__pycache__/__init__.cpython-36.pyc b/services/__pycache__/__init__.cpython-36.pyc
new file mode 100644
index 0000000..aa1eba2
--- /dev/null
+++ b/services/__pycache__/__init__.cpython-36.pyc
Binary files differ
diff --git a/services/__pycache__/constants.cpython-36.pyc b/services/__pycache__/constants.cpython-36.pyc
new file mode 100644
index 0000000..f2635de
--- /dev/null
+++ b/services/__pycache__/constants.cpython-36.pyc
Binary files differ
diff --git a/services/__pycache__/helper.cpython-36.pyc b/services/__pycache__/helper.cpython-36.pyc
new file mode 100644
index 0000000..60cf12a
--- /dev/null
+++ b/services/__pycache__/helper.cpython-36.pyc
Binary files differ
diff --git a/services/__pycache__/session.cpython-36.pyc b/services/__pycache__/session.cpython-36.pyc
new file mode 100644
index 0000000..eeb05fe
--- /dev/null
+++ b/services/__pycache__/session.cpython-36.pyc
Binary files differ
diff --git a/services/__pycache__/types.cpython-36.pyc b/services/__pycache__/types.cpython-36.pyc
new file mode 100644
index 0000000..b07c3cf
--- /dev/null
+++ b/services/__pycache__/types.cpython-36.pyc
Binary files differ
diff --git a/services/api/__init__.py b/services/api/__init__.py
new file mode 100644
index 0000000..30d7152
--- /dev/null
+++ b/services/api/__init__.py
@@ -0,0 +1,38 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
diff --git a/services/api/__pycache__/__init__.cpython-36.pyc b/services/api/__pycache__/__init__.cpython-36.pyc
new file mode 100644
index 0000000..ece5c7a
--- /dev/null
+++ b/services/api/__pycache__/__init__.cpython-36.pyc
Binary files differ
diff --git a/services/api/__pycache__/api_bridge.cpython-36.pyc b/services/api/__pycache__/api_bridge.cpython-36.pyc
new file mode 100644
index 0000000..1da6617
--- /dev/null
+++ b/services/api/__pycache__/api_bridge.cpython-36.pyc
Binary files differ
diff --git a/services/api/__pycache__/api_checklist.cpython-36.pyc b/services/api/__pycache__/api_checklist.cpython-36.pyc
new file mode 100644
index 0000000..6ea208f
--- /dev/null
+++ b/services/api/__pycache__/api_checklist.cpython-36.pyc
Binary files differ
diff --git a/services/api/__pycache__/api_gitlab.cpython-36.pyc b/services/api/__pycache__/api_gitlab.cpython-36.pyc
new file mode 100644
index 0000000..d4dedbc
--- /dev/null
+++ b/services/api/__pycache__/api_gitlab.cpython-36.pyc
Binary files differ
diff --git a/services/api/__pycache__/api_jenkins.cpython-36.pyc b/services/api/__pycache__/api_jenkins.cpython-36.pyc
new file mode 100644
index 0000000..905295c
--- /dev/null
+++ b/services/api/__pycache__/api_jenkins.cpython-36.pyc
Binary files differ
diff --git a/services/api/__pycache__/api_user.cpython-36.pyc b/services/api/__pycache__/api_user.cpython-36.pyc
new file mode 100644
index 0000000..1893ff4
--- /dev/null
+++ b/services/api/__pycache__/api_user.cpython-36.pyc
Binary files differ
diff --git a/services/api/__pycache__/api_virtual_function.cpython-36.pyc b/services/api/__pycache__/api_virtual_function.cpython-36.pyc
new file mode 100644
index 0000000..35349c5
--- /dev/null
+++ b/services/api/__pycache__/api_virtual_function.cpython-36.pyc
Binary files differ
diff --git a/services/api/api_bridge.py b/services/api/api_bridge.py
new file mode 100644
index 0000000..8926a1d
--- /dev/null
+++ b/services/api/api_bridge.py
@@ -0,0 +1,74 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+class APIBridge:
+
+ """
+ This class helps to use functions inside classes with circular import (dependencies).
+ Use this class only when there is circular import in one of the API services.
+ """
+
+ @staticmethod
+ def is_gitlab_ready(user_content):
+ """is_gitlab_ready: Originally can be found under APIGitLab class."""
+ from services.api.api_gitlab import APIGitLab
+ return APIGitLab.is_gitlab_ready(user_content)
+
+ @staticmethod
+ def login_user(email):
+ """login_user: Originally can be found under APIUser class."""
+ from services.api.api_user import APIUser
+ return APIUser.login_user(email)
+
+ @staticmethod
+ def set_ssh(user_content, sshKey):
+ """set_ssh: Originally can be found under APIUser class."""
+ from services.api.api_user import APIUser
+ return APIUser.set_ssh(user_content, sshKey)
+
+ @staticmethod
+ def create_engagement(wait_for_gitlab=True):
+ """create_engagement: Originally can be found under APIVirtualFunction class."""
+ from services.api.api_virtual_function import APIVirtualFunction
+ return APIVirtualFunction.create_engagement(wait_for_gitlab)
+
+ @staticmethod
+ def frontend_login(email, password):
+ """login: Originally can be found under FEUser class."""
+ from services.frontend.fe_user import FEUser
+ return FEUser.login(email, password)
diff --git a/services/api/api_checklist.py b/services/api/api_checklist.py
new file mode 100644
index 0000000..ef7b8a3
--- /dev/null
+++ b/services/api/api_checklist.py
@@ -0,0 +1,219 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import datetime
+import logging
+
+import requests
+
+from services.api.api_gitlab import APIGitLab
+from services.api.api_user import APIUser
+from services.constants import Constants
+from services.database.db_general import DBGeneral
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+
+
+logger = LoggingServiceFactory.get_logger()
+
+
+class APIChecklist:
+
+ @staticmethod
+ def create_checklist(user_content, files=["file0", "file1"], return_negative_response=False):
+ r1 = None
+ postURL = Constants.Default.URL.Checklist.TEXT + \
+ user_content['engagement_uuid'] + '/checklist/new/'
+ logger.debug("Post create checklist URL: " + postURL)
+ headers = dict()
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = user_content['session_token']
+ data = dict()
+ data['checkListAssociatedFiles'] = files
+ data['checkListName'] = "checklistAPI" + \
+ Helper.rand_string('randomString')
+ data['checkListTemplateUuid'] = DBGeneral.select_where(
+ "uuid", "ice_checklist_template", "name", Constants.Template.Heat.TEXT, 1)
+ try:
+ if not APIGitLab.is_gitlab_ready(user_content):
+ raise Exception(
+ "Gitlab is not ready and because of that the test is failed.")
+
+ r1 = requests.post(postURL, json=data,
+ headers=headers, verify=False)
+
+ Helper.internal_assert_boolean(r1.status_code, 200)
+ logger.debug("Checklist was created successfully!")
+ cl_content = r1.json()
+ return cl_content
+ except:
+ if return_negative_response:
+ return r1
+ if r1 is None:
+ logger.error(
+ "Failed to create checklist for VF " + user_content['vfName'])
+ else:
+ logger.error("Failed to create checklist for VF " + user_content[
+ 'vfName'] + ", see response >>> %s %s.\nContent: %s" % (r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def update_checklist(user_content, cl_uuid):
+ r1 = None
+ postURL = Constants.Default.URL.Checklist.Update.TEXT + '/' + cl_uuid
+ logger.debug("Post create checklist URL: " + postURL + '/' + cl_uuid)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = user_content['session_token']
+ data = dict() # Create JSON data for post request.
+ data['checklistUuid'] = cl_uuid
+ data['checkListAssociatedFiles'] = ["file1", "file2"]
+ data['checkListName'] = "UpdateChecklistAPI" + \
+ Helper.rand_string('randomString')
+ data['checkListTemplateUuid'] = DBGeneral.select_where(
+ "uuid", "ice_checklist_template", "name", Constants.Template.Heat.TEXT, 1)
+ try:
+ r1 = requests.put(
+ postURL, json=data, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ logger.debug("DBChecklist was created successfully!")
+ cl_content = r1.json()
+ return cl_content['uuid']
+ except:
+ if r1 is None:
+ logger.error(
+ "Failed to create checklist for VF " + user_content['vfName'])
+ else:
+ logger.error("Failed to create checklist for VF " + user_content[
+ 'vfName'] + ", see response >>> %s %s.\nContent: %s" % (r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def add_checklist_audit_log(user_content, cl_uuid):
+ r1 = None
+ postURL = Constants.Default.URL.Checklist.Update + \
+ cl_uuid + '/auditlog/'
+ logger.debug("Post checklist audit log URL: " + postURL)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = user_content['session_token']
+ data = dict() # Create JSON data for post request.
+ data['description'] = "API audit log test " + \
+ Helper.rand_string('randomString')
+ try:
+ r1 = requests.post(
+ postURL, json=data, headers=headers, verify=False)
+ Helper.internal_assert_boolean(r1.status_code, 200)
+ logger.debug("Audit log was added successfully!")
+ except:
+ if r1 is None:
+ logger.error(
+ "Failed to add audit log for checklist uuid: " + cl_uuid)
+ else:
+ logger.error("Failed to add audit log for checklist uuid: " + cl_uuid +
+ ", see response >>> %s %s.\nContent: %s" % (r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def add_checklist_next_step(user_content, cl_uuid):
+ r1 = None
+ postURL = Constants.Default.URL.Checklist.TEXT + \
+ user_content['engagement_uuid'] + \
+ '/checklist/' + cl_uuid + '/nextstep/'
+ logger.debug("Post checklist next step URL: " + postURL)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = user_content['session_token']
+ data = dict() # Create JSON data for post request.
+ data['files'] = ["file0"]
+ data['assigneesUuids'] = [user_content['uuid']]
+ data['duedate'] = str(datetime.date.today())
+ data['description'] = "API next step test " + \
+ Helper.rand_string('randomString')
+ list_data = []
+ list_data.append(data)
+ try:
+ r1 = requests.post(
+ postURL, json=list_data, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ logger.debug("Next step was added successfully!")
+ ns_uuid = r1.json()
+ return ns_uuid[0]['uuid']
+ except:
+ if r1 is None:
+ logger.error(
+ "Failed to add next step for checklist uuid: " + cl_uuid)
+ else:
+ logger.error("Failed to add next step for checklist uuid: " + cl_uuid +
+ ", see response >>> %s %s.\nContent: %s" % (r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def jump_state(checklistUUID, engLeadEmail):
+ token = APIUser.login_user(engLeadEmail)
+ stateURL = Constants.Default.URL.Checklist.Rest.TEXT + \
+ str(checklistUUID) + '/state/'
+ APIChecklist.go_to_next_state(stateURL, token)
+
+ @staticmethod
+ def go_to_next_state(url, token):
+ headers = {"Authorization": "token " + token}
+ body = dict()
+ body['description'] = ""
+ body['decline'] = "False"
+ r = requests.put(url, headers=headers, json=body, verify=False)
+ if (r.status_code == 201 or r.status_code == 200):
+ logger.debug("go_to_next_state put request result status: %s" %
+ r.status_code)
+ else:
+ logger.error(
+ "PUT request failed to change checklist state >>> " + str(r.status_code) + " " + r.reason)
+ raise Exception("PUT request failed to change checklist state")
+
+ @staticmethod
+ def move_cl_to_closed(cl_uuid, vf_staff_emails):
+ api_checklist_obj = APIChecklist()
+
+ for i in range(len(vf_staff_emails)):
+ logger.debug("Trying to jump state for %s [%s]" % (vf_staff_emails[i], i))
+ api_checklist_obj.jump_state(cl_uuid, vf_staff_emails[i])
+
+ # Move CL to closed state.
+ logger.debug("Trying to jump state 'closed' for %s" % vf_staff_emails[0])
+ api_checklist_obj.jump_state(cl_uuid, vf_staff_emails[0])
+
diff --git a/services/api/api_gitlab.py b/services/api/api_gitlab.py
new file mode 100644
index 0000000..c7b25e0
--- /dev/null
+++ b/services/api/api_gitlab.py
@@ -0,0 +1,394 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import logging
+import os
+import subprocess
+import sys
+import time
+
+from django.conf import settings
+import git
+import requests
+
+from services.api.api_bridge import APIBridge
+from services.constants import Constants
+from services.database.db_virtual_function import DBVirtualFunction
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class APIGitLab:
+
+ @staticmethod
+ def display_output(p):
+ while True:
+ out = p.stderr.read(1)
+ if out == b'' and p.poll() != None:
+ break
+ if out != '':
+ sys.stdout.write(str(out.decode()))
+ sys.stdout.flush()
+
+ @staticmethod
+ def get_git_project(path_with_namespace):
+ r1 = None
+ getURL = Constants.Default.URL.GitLab.Projects.TEXT + \
+ path_with_namespace
+ logger.debug("Get project URL: " + getURL)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['PRIVATE-TOKEN'] = settings.GITLAB_TOKEN
+ try:
+ r1 = requests.get(getURL, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ counter = 0
+ while r1.content == b'[]' and counter <= Constants.GitLabConstants.RETRIES_NUMBER:
+ time.sleep(session.wait_until_time_pause)
+ r1 = requests.get(getURL, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+
+ if r1.content == b'[]':
+ logger.error("Got an empty list as a response.")
+ raise
+ logger.debug("Project exists on APIGitLab!")
+ content = r1.json() # Change it from list to dict.
+ return content
+ except:
+ if r1 is None:
+ logger.error("Failed to get project from APIGitLab.")
+ else:
+ logger.error("Failed to get project from APIGitLab, see response >>> %s %s \n %s"
+ % (r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ def are_all_list_users_registered_as_project_members(self, users_emails_list, project_path_with_namespace):
+ for email in users_emails_list:
+ if not self.validate_git_project_members(project_path_with_namespace, email):
+ raise Exception(
+ "Couldn't find the invited users: " + email + " in GitLab.")
+ logger.debug(
+ "Invited user: " + email + " found in GitLab.")
+
+ @staticmethod
+ def validate_git_project_members(path_with_namespace, user_email):
+ if settings.DATABASE_TYPE != 'local':
+ r1 = None
+ headers = dict()
+ git_user = APIGitLab.get_git_user(user_email)
+ getURL = Constants.Default.URL.GitLab.Projects.TEXT + \
+ path_with_namespace + "/members/" + str(git_user['id'])
+ logger.debug("Get project members URL: " + getURL)
+ headers['Content-type'] = 'application/json'
+ headers['PRIVATE-TOKEN'] = settings.GITLAB_TOKEN
+ counter = 0
+ while (r1 is None or r1.content == b'[]' or r1.status_code != 200) and counter <= Constants.GitLabConstants.RETRIES_NUMBER:
+ logger.debug(
+ "try to get git project members (try #%s)" % counter)
+ time.sleep(session.wait_until_time_pause)
+ try:
+ r1 = requests.get(getURL, headers=headers, verify=False)
+ counter += 1
+ except Exception as e:
+ if counter >= Constants.GitLabConstants.RETRIES_NUMBER:
+ logger.error("Failed to get project's team members from APIGitLab, see response >>> %s %s \n %s %s"
+ % (r1.status_code, r1.reason, str(r1.content, 'utf-8'), e.message))
+ return False
+ if r1.content == b'[]':
+ logger.error("Got an empty list as a response.")
+ return False
+ elif r1.status_code != 200:
+ logger.error("Got %s %s." % (r1.status_code, r1.reason))
+ return False
+ logger.debug("Got %s %s, user found in project." %
+ (r1.status_code, r1.reason))
+ return True
+
+ @staticmethod
+ def negative_validate_git_project_member(path_with_namespace, user_email, git_user_id):
+ if settings.DATABASE_TYPE != 'local':
+ r1 = None
+ headers = dict()
+ getURL = Constants.Default.URL.GitLab.Projects.TEXT + \
+ path_with_namespace + "/members/" + git_user_id
+ logger.debug("Get project members URL: " + getURL)
+ headers['Content-type'] = 'application/json'
+ headers['PRIVATE-TOKEN'] = settings.GITLAB_TOKEN
+ counter = 0
+ while r1 is None or str.encode(user_email) not in r1.content and counter <= Constants.GitLabConstants.RETRIES_NUMBER:
+ logger.debug(
+ "try to get git project members (try #%s)" % counter)
+ time.sleep(session.wait_until_time_pause)
+ try:
+ r1 = requests.get(getURL, headers=headers, verify=False)
+ counter += 1
+ except Exception as e:
+ if counter >= Constants.GitLabConstants.RETRIES_NUMBER:
+ logger.error("Failed to get project's team members from APIGitLab, see response >>> %s %s \n %s %s"
+ % (r1.status_code, r1.reason, str(r1.content, 'utf-8'), e.message))
+ return False
+
+ if r1.content == b'[]':
+ logger.debug("Got %s %s, user not found in project." %
+ (r1.status_code, r1.reason))
+ return True
+ else:
+ logger.debug("Got %s %s, user found in project." %
+ (r1.status_code, r1.reason))
+ return False
+
+ @staticmethod
+ def get_git_user(user_email):
+ if settings.DATABASE_TYPE != 'local':
+ r1 = None
+ user_email = user_email.replace("@", "_at_")
+ getURL = settings.GITLAB_URL + \
+ "api/v3/users?username=" + user_email
+ logger.debug("Get user URL: " + getURL)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['PRIVATE-TOKEN'] = settings.GITLAB_TOKEN
+ try:
+ r1 = requests.get(getURL, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ counter = 0
+ while r1.content == b'[]' and counter <= 60:
+ logger.info(
+ "Will try to get gitlab user until will be response... #%s" % counter)
+ time.sleep(session.wait_until_time_pause_long)
+ r1 = requests.get(getURL, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ counter += 1
+
+ if r1.content == b'[]':
+ logger.error("Got an empty user from gitlab.")
+ raise Exception("Got an empty user from gitlab.")
+
+ logger.debug("Got %s %s and received user data: %s." %
+ (r1.status_code, r1.reason, r1.content))
+ content = r1.json()
+ return content[0]
+ except:
+ if r1 is None:
+ logger.error("Failed to get user from APIGitLab.")
+ else:
+ logger.error("Failed to get user from APIGitLab, see response >>> %s %s \n %s"
+ % (r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def get_git_user_ssh_key(git_user_id):
+ r1 = None
+ getURL = Constants.Default.URL.GitLab.Users.TEXT + \
+ str(git_user_id) + "/keys"
+ logger.debug("Get user URL: " + getURL)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['PRIVATE-TOKEN'] = settings.GITLAB_TOKEN
+ try:
+ r1 = requests.get(getURL, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ if r1.content == '[]':
+ logger.error("Got an empty list as a response.")
+ raise
+ logger.debug("Got %s %s and received user's public key." %
+ (r1.status_code, r1.reason))
+ content = r1.json() # Change it from list to dict.
+ gitPubKey = content[0]['key']
+ return gitPubKey
+ except:
+ if r1 is None:
+ logger.error("Failed to get user's public key from APIGitLab.")
+ else:
+ logger.error("Failed to get user's public key from APIGitLab, see response >>> %s %s \n %s"
+ % (r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def git_clone_push(user_content):
+ if settings.DATABASE_TYPE != 'local':
+ logger.debug(
+ "About to push files into project's repository on the local folder(not over origin).")
+ try:
+ user_content['session_token'] = "token " + \
+ APIBridge.login_user(Constants.Users.Admin.EMAIL)
+ used_email_for_actions = Constants.Users.Admin.EMAIL
+ repo_dir = Constants.Paths.LocalGitFolder.PATH + \
+ user_content['vfName']
+ if not os.path.exists(repo_dir):
+ os.makedirs(repo_dir)
+ logger.debug("Created the following folder: %s" % repo_dir)
+ # Create pair of keys for user.
+ user_pub_key = Helper.get_or_create_rsa_key_for_admin()
+ DBVirtualFunction.add_admin_to_eng_team(
+ user_content['engagement_uuid'])
+ # Set SSH Key for the user.
+ APIBridge.set_ssh(user_content, user_pub_key)
+ git_user = APIGitLab.get_git_user(used_email_for_actions)
+
+ counter = 0
+ git_user_pub_key = None
+ while user_pub_key != git_user_pub_key and counter < Constants.GitLabConstants.RETRIES_NUMBER:
+ try:
+ git_user_pub_key = APIGitLab.get_git_user_ssh_key(
+ git_user['id'])
+ except Exception as e:
+ pass
+
+ counter += 1
+ time.sleep(session.wait_until_time_pause)
+
+ # Check that the SSH key was added to user on APIGitLab.
+ if user_pub_key != git_user_pub_key:
+ raise Exception("The SSH Key received does not equal to the"
+ " one provided! The key from"
+ "APIGitLab:\n %s ==<>== %s"
+ % (git_user_pub_key, user_pub_key))
+
+ gitRepoURL = "git@gitlab:%s/%s.git" % (
+ user_content['engagement_manual_id'], user_content['vfName'])
+ logger.debug("Clone repo from: " + gitRepoURL)
+ APIGitLab.is_gitlab_ready(user_content)
+ cmd = 'cd ' + repo_dir + \
+ '; git config --global user.email \"' + Constants.Users.Admin.EMAIL + \
+ '\"; git config --global user.name \"' + \
+ Constants.Users.Admin.FULLNAME + '\";'
+ # Commit all changes.
+ p = subprocess_popen = subprocess.Popen(
+ cmd, shell=True, stderr=subprocess.PIPE)
+ while subprocess_popen is None:
+ logger.debug(
+ "waiting to subprocess command to complete...")
+ APIGitLab.display_output(p)
+ # Clone project from APIGitLab.
+ repo = git.Repo.clone_from(gitRepoURL, repo_dir)
+ logger.debug("Successfully cloned repo to " + repo_dir)
+ # Create three files (file0, file1, file2) and add them to git
+ # index.
+ for i in range(3):
+ fileName = repo_dir + '/file' + str(i)
+ with open(fileName, 'w') as content_file:
+ os.chmod(fileName, 0o600)
+ content_file.write("Test file " + fileName)
+ repo.index.add([fileName])
+ logger.debug(
+ fileName + " was created and added to commit list.")
+ cmd = 'cd ' + repo_dir + \
+ '; git commit -a -m \"Create and add 3 files to git.\"'
+ # Commit all changes.
+ p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
+ APIGitLab.display_output(p)
+ logger.debug("All files added to commit list.")
+ cmd = 'cd ' + repo_dir + '; git push'
+ # Push commit to APIGitLab.
+ p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
+ APIGitLab.display_output(p)
+ logger.debug("All files were pushed to APIGitLab.")
+ except Exception as e:
+ logger.error(
+ "_-_-_-_-_- Unexpected error in git_clone_push: " + str(e))
+ raise Exception(e)
+
+ @staticmethod
+ def git_push_commit(user_content):
+ if settings.DATABASE_TYPE != 'local':
+ logger.debug(
+ "About to push files into project's repository on APIGitLab")
+ try:
+ git_work = '/tmp/git_work/'
+ repo_dir = git_work + user_content['vfName']
+ # Create three files (file0, file1, file2) and add them to git
+ # index.
+ for i in range(3):
+ fileName = repo_dir + '/file' + str(i)
+ with open(fileName, 'w') as content_file:
+ os.chmod(fileName, 0o600)
+ content_file.write("Edit test file " + fileName)
+ logger.debug(fileName + " was edited.")
+ cmd = 'cd ' + repo_dir + \
+ '; git commit -a -m \"Create and add 3 files to git.\"'
+ # Commit all changes.
+ p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
+ APIGitLab.display_output(p)
+ logger.debug("All edited files were committed.")
+ cmd = 'cd ' + repo_dir + '; git push'
+ # Push commit to APIGitLab.
+ p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
+ APIGitLab.display_output(p)
+ logger.debug(
+ "All edited files were commited and pushed to APIGitLab.")
+ except Exception as e:
+ logger.error(
+ "_-_-_-_-_- Unexpected error in git_push_commit : " + str(e))
+ raise Exception(
+ "Something went wrong on git_push_commit function, please check logs.")
+
+ @staticmethod
+ def is_gitlab_ready(user_content):
+ counter = 1
+ gettURL = settings.ICE_EM_URL + '/v1/engmgr/engagement/' + \
+ user_content['engagement_uuid'] + '/checklist/new/'
+ logger.debug(
+ "Get URL to check if GitLab and Jenkins are ready: " + gettURL)
+ # Validate with EL
+ token = "token " + APIBridge.login_user(user_content['el_email'])
+ headers = dict() # Create header for get request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = token
+ r1 = requests.get(gettURL, headers=headers, verify=False)
+ while (r1.content == b'"Create New checklist is not ready yet"' and counter <=
+ Constants.GitLabConstants.RETRIES_NUMBER):
+ time.sleep(session.wait_until_time_pause_long)
+ logger.debug(
+ "GitLab and Jenkins are not ready yet, trying again (%s of %s)" %
+ (counter, Constants.GitLabConstants.RETRIES_NUMBER))
+ r1 = requests.get(gettURL, headers=headers, verify=False)
+ counter += 1
+ if r1.status_code != 200:
+ if r1.content == "Create New checklist is not ready yet":
+ raise Exception("Max retries exceeded, failing test...")
+ else:
+ raise Exception("Something went wrong while waiting for GitLab and Jenkins. %s %s" % (
+ r1.status_code, r1.reason))
+ return False
+ elif r1.status_code == 200:
+ logger.debug("Gitlab and Jenkins are ready to continue!")
+ return True
diff --git a/services/api/api_jenkins.py b/services/api/api_jenkins.py
new file mode 100644
index 0000000..e1e1f6e
--- /dev/null
+++ b/services/api/api_jenkins.py
@@ -0,0 +1,81 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from django.conf import settings
+import requests
+from requests.auth import HTTPBasicAuth
+
+from services.constants import Constants
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class APIJenkins:
+
+ @staticmethod
+ def get_jenkins_job(job_name):
+ r1 = None
+ getURL = settings.JENKINS_URL + "job/" + job_name
+ logger.debug("Get APIJenkins job URL: " + getURL)
+ try:
+ r1 = requests.get(getURL, auth=HTTPBasicAuth(
+ settings.JENKINS_USERNAME, settings.JENKINS_PASSWORD))
+ Helper.internal_assert(r1.status_code, 200)
+ logger.debug("Job was created on APIJenkins!")
+ except:
+ msg = None
+
+ if r1 is None:
+ msg = "APIJenkins didn't create job for %s" % job_name
+ else:
+ msg = "APIJenkins didn't create job for %s, see response >>> %s %s" % (
+ job_name, r1.status_code, r1.reason)
+
+ logger.error(msg)
+ raise Exception(msg)
+
+ @staticmethod
+ def find_build_num_out_of_jenkins_log(log):
+ lines_array = log.splitlines()
+ for line in lines_array:
+ if Constants.Dashboard.Checklist.JenkinsLog.Modal.Body.BUILD_IDENTIFIER in line:
+ parts = line.partition('jenkins')
+ return parts[2]
+
diff --git a/services/api/api_rados.py b/services/api/api_rados.py
new file mode 100644
index 0000000..61cfa5c
--- /dev/null
+++ b/services/api/api_rados.py
@@ -0,0 +1,161 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import logging
+import time
+
+from boto.s3.connection import S3Connection, OrdinaryCallingFormat
+from django.conf import settings
+
+from rados.rgwa_client_factory import RGWAClientFactory
+from services.constants import Constants
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class APIRados:
+
+ @staticmethod
+ def get_bucket(name):
+ """Return the Bucket."""
+ boto_conn = RGWAClientFactory.standard()
+ try:
+ return boto_conn.lookup(name)
+ except Exception as e:
+ logger.error("Problem on get bucket", e)
+ raise e
+
+ @staticmethod
+ def get_bucketfor_specific_user(name, access_key_id, secret_access_key):
+ """Return the Bucket."""
+ boto_conn = APIRados.specific_client(access_key_id, secret_access_key)
+ try:
+ return boto_conn.lookup(name)
+ except Exception as e:
+ logger.error("Problem on get bucket for specific user", e)
+ raise e
+
+ @staticmethod
+ def get_bucket_grants(bucket_name):
+ """Return the Grants."""
+ counter = 1
+ bucket = APIRados.get_bucket(bucket_name)
+ while not bucket and counter <= Constants.RGWAConstants.BUCKET_RETRIES_NUMBER:
+ logger.error("Bucket not found. Retry #%s" % counter)
+ time.sleep(session.wait_until_time_pause_long)
+ bucket = APIRados.get_bucket(bucket_name)
+ counter += 1
+ if not bucket:
+ raise TimeoutError("Max retries exceeded, failing test...")
+ grants = bucket.list_grants()
+ print("***********grants=", grants)
+ return grants
+
+ @staticmethod
+ def is_bucket_ready(bucket_id):
+ counter = 1
+ bucket = APIRados.get_bucket(bucket_id)
+ while (bucket == None and counter <=
+ Constants.RGWAConstants.BUCKET_RETRIES_NUMBER):
+ time.sleep(session.wait_until_time_pause_long)
+ logger.debug(
+ "bucket are not ready yet, trying again (%s of 180)" % counter)
+ bucket = APIRados.get_bucket(bucket_id)
+ counter += 1
+ print("****_+__+bucket= ", str(bucket))
+ time.sleep(session.wait_until_time_pause_long)
+ if bucket == None:
+ raise TimeoutError("Max retries exceeded, failing test...")
+ elif bucket != None:
+ logger.debug("bucket are ready to continue!")
+ return True
+
+ @staticmethod
+ def users_of_bucket_ready_after_complete(bucket_id, user_name):
+ grants = APIRados.get_bucket_grants(bucket_id)
+ count = 0
+ counter = 1
+ while (count != 0 and counter <=
+ Constants.RGWAConstants.BUCKET_RETRIES_NUMBER):
+ grants = APIRados.get_bucket_grants(bucket_id)
+ time.sleep(session.wait_until_time_pause_long)
+ for g in grants:
+ if g.id == user_name:
+ count = +1
+ time.sleep(session.wait_until_time_pause_long)
+ if count != 0:
+ raise Exception("Max retries exceeded, failing test...")
+ return False
+ elif count == 0:
+ logger.debug("users_of_bucket are ready to continue!")
+ return True
+
+ @staticmethod
+ def users_of_bucket_ready_after_created(bucket_id, user_name):
+ grants = APIRados.get_bucket_grants(bucket_id)
+ count = 0
+ counter = 1
+ while (count == 0 and counter <=
+ Constants.RGWAConstants.BUCKET_RETRIES_NUMBER):
+ grants = APIRados.get_bucket_grants(bucket_id)
+ time.sleep(session.wait_until_time_pause_long)
+ for g in grants:
+ if g.id == user_name:
+ count = +1
+ time.sleep(session.wait_until_time_pause_long)
+ if count == 0:
+ raise Exception("Max retries exceeded, failing test...")
+ return False
+ elif count > 0:
+ logger.debug("users_of_bucket are ready to continue!")
+ return True
+
+ @staticmethod
+ def specific_client(access_key_id, secret_access_key):
+ boto_conn = S3Connection(
+ host=settings.AWS_S3_HOST,
+ port=settings.AWS_S3_PORT,
+ aws_access_key_id=access_key_id,
+ aws_secret_access_key=secret_access_key,
+ calling_format=OrdinaryCallingFormat(),
+ is_secure=True,)
+
+ boto_conn.num_retries = 0
+ return boto_conn
diff --git a/services/api/api_user.py b/services/api/api_user.py
new file mode 100644
index 0000000..3e38fd2
--- /dev/null
+++ b/services/api/api_user.py
@@ -0,0 +1,308 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import re
+
+from django.conf import settings
+import requests
+
+from services.api.api_bridge import APIBridge
+from services.api.api_gitlab import APIGitLab
+from services.constants import Constants, ServiceProvider
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class APIUser:
+
+ @staticmethod
+ # Update account API - only adds new SSH key!
+ def update_account(user_content):
+ r1 = None
+ token = APIUser.login_user(user_content['email'])
+ user_content['session_token'] = 'token ' + token
+ sshKey = Helper.generate_sshpub_key()
+ putURL = settings.ICE_EM_URL + '/v1/engmgr/users/account'
+ logger.debug("Put user URL: " + putURL)
+ headers = dict() # Create header for put request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = user_content['session_token']
+ # headers['Authorization'] = user_content['activation_token']
+ put_data = dict() # Create JSON data for put request.
+ user_content['vendor'] = user_content['company']['name']
+ if user_content['vendor'] == "AT&amp;T":
+ put_data['company'] = "AT&T"
+ else:
+ put_data['company'] = user_content['vendor']
+ put_data['email'] = user_content['email']
+ put_data['full_name'] = user_content['full_name']
+ put_data['password'] = ""
+ put_data['phone_number'] = "+1201" + \
+ Helper.rand_string("randomNumber", 6)
+ put_data['ssh_key'] = sshKey
+ try:
+ r1 = requests.put(
+ putURL, json=put_data, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ logger.debug(
+ "SSH Key was added successfully to user " + user_content['full_name'])
+ if not APIBridge.is_gitlab_ready(user_content):
+ raise
+ return sshKey
+ except:
+ if r1 is None:
+ logger.error("Failed to add public SSH key to user.")
+ else:
+ logger.error("PUT request failed to add SSH key to user, see response >>> %s %s \n %s" % (
+ r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ # Update account API - only adds new SSH key!
+ def update_account_injec_script(user_content):
+ r1 = None
+ putURL = settings.ICE_EM_URL + '/v1/engmgr/users/account'
+ logger.debug("Put user URL: " + putURL)
+ headers = dict() # Create header for put request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = user_content['session_token']
+ put_data = dict() # Create JSON data for put request.
+ if user_content['vendor'] == "AT&amp;T":
+ put_data['company'] = "AT&T"
+ else:
+ put_data['company'] = user_content['vendor']
+ put_data['email'] = user_content['email']
+ script = "<script>;</script>"
+ put_data['full_name'] = script
+ put_data['password'] = ""
+ put_data['phone_number'] = "+1201" + \
+ Helper.rand_string("randomNumber", 6)
+ try:
+ r1 = requests.put(
+ putURL, json=put_data, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ msg = "Testing for Cross site scripting successfully : " + \
+ user_content['full_name'] + \
+ "stattus Code = " + str(r1.status_code)
+ logger.debug(msg)
+ if not APIBridge.is_gitlab_ready(user_content):
+ raise
+ return True
+ except:
+ if r1 is None:
+ logger.error("Failed to add public SSH key to user.")
+ else:
+ logger.error("PUT request failed to add SSH key to user, see response >>> %s %s \n %s" % (
+ r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def create_new_user(company=False, activate=False):
+ signupUrl = settings.EM_REST_URL + "signup/"
+ signupParams = APIUser.create_signup_param(company)
+ r1 = requests.post(signupUrl, json=signupParams, verify=False)
+ if (r1.status_code == 201 or r1.status_code == 200):
+ logger.debug("Moving to next test case. status=" +
+ str(r1.status_code))
+ pass # Need to break here.
+ try:
+ user_data = r1.json()
+ except Exception as e:
+ logger.error("=========== json error ========")
+ logger.error("r1.content = " + str(r1.content) +
+ ", status=" + str(r1.status_code))
+ logger.error("=========== json error end ========")
+ raise e
+ if activate:
+ APIUser.activate_user(
+ user_data['uuid'], user_data["user"]["activation_token"])
+ return user_data
+
+ @staticmethod
+ def login_user(email):
+ postUrl = settings.EM_REST_URL + "login"
+ user_data = dict() # Create JSON data for post request.
+ user_data['email'] = email
+ user_data['password'] = "iceusers"
+ try:
+ headers = {'Content-type': 'application/json'}
+ r = requests.post(
+ postUrl, json=user_data, headers=headers, verify=False)
+ logger.debug(str(r.status_code) + " " + r.reason)
+ decoded_response = r.json()
+ return decoded_response['token']
+ except:
+ logger.debug("Failed to login.")
+ raise
+
+ @staticmethod
+ def set_ssh(user_content, sshKey=None): # Set SSH key to user.
+ r1 = None
+ if sshKey is None:
+ logger.debug("About to generate an ssh key for the user: %s" %
+ user_content['email'])
+ sshKey = Helper.generate_sshpub_key()
+ postURL = settings.ICE_EM_URL + '/v1/engmgr/users/ssh'
+ logger.debug("Post user URL: " + postURL)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = user_content['session_token']
+ post_data = dict() # Create JSON data for post request.
+ post_data['ssh_key'] = sshKey
+ try:
+ r1 = requests.post(
+ postURL, json=post_data, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ logger.debug(
+ "SSH Key was added successfully")
+ if not APIBridge.is_gitlab_ready(user_content):
+ raise
+ return sshKey
+ except:
+ if r1 is None:
+ logger.error("Failed to add public SSH key.")
+ else:
+ logger.error(
+ "POST request failed to add SSH key to user, see response >>> %s %s" % (r1.status_code, r1.reason))
+ raise
+
+ @staticmethod
+ def create_signup_param(company=False):
+ try: # Click on element in UI, by xPath locator.
+ if not company:
+ company = ServiceProvider.MainServiceProvider
+ email_domain = ServiceProvider.email
+ else:
+ email_domain = company.lower() + ".com" #
+ data = {
+ "company": company,
+ "full_name": Helper.rand_string("randomString"),
+ "email": Helper.rand_string("randomString") + "@" + email_domain,
+ "phone_number": Constants.Default.Phone.TEXT,
+ "password": Constants.Default.Password.TEXT,
+ "regular_email_updates": "True"
+ }
+
+ return data
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Could not create Sign Up parametrs"
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def activate_user(userUuid, activationToken):
+ postUrl = settings.ICE_EM_URL + "/v1/engmgr/users/activate/" + \
+ userUuid + "/" + activationToken
+ logger.debug(postUrl)
+ r1 = requests.get(postUrl, verify=False)
+ if (r1.status_code == 200):
+ logger.debug("APIUser activated successfully!")
+ return True
+ else:
+ raise Exception(
+ "Failed to activate user >>> %s %s" % (r1.status_code, r1.reason))
+
+ @staticmethod
+ def signup_invited_user(company, invited_email, invite_token, invite_url, user_content, is_contact_user="false", activate=False, wait_for_gitlab=True):
+ r1 = None
+ postURL = settings.ICE_EM_URL + '/v1/engmgr/signup'
+ logger.debug("Post signup URL: " + postURL)
+ if is_contact_user == "true":
+ fullName = re.sub("http.*full_name=", "", invite_url)
+ fullName = re.sub("&.*", "", fullName)
+ logger.debug(
+ "Invited contact full name is (according to url): " + fullName)
+ else:
+ fullName = Helper.rand_string('randomString')
+
+ post_data = dict() # Create JSON data for post request.
+ post_data['company'] = company
+ post_data['email'] = invited_email
+ post_data['full_name'] = fullName
+ post_data['invitation'] = invite_token
+ post_data['is_contact_user'] = is_contact_user
+ post_data['password'] = "iceusers"
+ post_data['phone_number'] = "+1201" + \
+ Helper.rand_string("randomNumber", 6)
+ post_data['regular_email_updates'] = "False"
+ post_data['terms'] = "True"
+ try:
+ requests.get(invite_url, verify=False)
+ r1 = requests.post(
+ postURL, json=post_data, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ logger.debug("Invited user signed-up successfully!")
+
+ user_data = r1.json()
+ if activate:
+ APIUser.activate_user(
+ user_data['uuid'], user_data["user"]["activation_token"])
+
+ if wait_for_gitlab:
+ if not APIBridge.is_gitlab_ready(user_content):
+ raise
+ return post_data
+ except:
+ if r1 is None:
+ logger.error("Failed to sign up the invited team member.")
+ else:
+ logger.error("POST request failed to sign up the invited team member, see response >>> %s %s \n %s" % (
+ r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def create_new_user_content():
+ user_content = APIBridge.create_engagement()
+ APIGitLab.git_clone_push(user_content)
+ APIBridge.frontend_login(
+ user_content['email'], Constants.Default.Password.TEXT)
+ vfName = user_content['vfName']
+ uuid = user_content['uuid']
+ inviteEmail = Helper.rand_invite_email()
+ newObj = [vfName, uuid, inviteEmail]
+ return newObj, user_content
+
+ @staticmethod
+ def create_new_user_content_login_with_api():
+ user_content = APIBridge.create_engagement()
+ APIGitLab.git_clone_push(user_content)
+ token = "token " + APIBridge.login_user(user_content['el_email'])
+ user_content['session_token'] = token
+ return user_content
diff --git a/services/api/api_virtual_function.py b/services/api/api_virtual_function.py
new file mode 100644
index 0000000..46610e8
--- /dev/null
+++ b/services/api/api_virtual_function.py
@@ -0,0 +1,368 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import datetime
+import json
+import time
+
+from django.conf import settings
+import requests
+
+from services.api.api_gitlab import APIGitLab
+from services.api.api_user import APIUser
+from services.constants import Constants, ServiceProvider
+from services.database.db_general import DBGeneral
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+
+
+logger = LoggingServiceFactory.get_logger()
+
+
+class APIVirtualFunction:
+
+ @staticmethod
+ def add_next_step(user_content, files=[]):
+ r1 = None
+ postURL = settings.ICE_EM_URL + '/v1/engmgr/engagements/' + \
+ user_content['engagement_uuid'] + '/nextsteps'
+ logger.debug("Post add next step URL: " + postURL)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = user_content['session_token']
+ data = dict() # Create JSON data for post request.
+ files_list = list()
+ if type(files) is list:
+ for file in files:
+ files_list.append(file)
+ else:
+ files_list.append(files)
+ data['files'] = files_list
+ data['assigneesUuids'] = [user_content['uuid']]
+ data['duedate'] = str(datetime.date.today())
+ data['description'] = "API test - add next step."
+ list_data = []
+ list_data.append(data)
+ try:
+ r1 = requests.post(
+ postURL, json=list_data, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ logger.debug("Next step was added to the engagement!")
+ ns_uuid = r1.json()
+ return ns_uuid[0]['uuid']
+ except:
+ if r1 is None:
+ logger.error(
+ "Failed to add next step to VF " + user_content['vfName'])
+ else:
+ logger.error("Failed to add next step to VF " + user_content[
+ 'vfName'] + ", see response >>> %s %s.\nContent: %s" % (r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def create_vf(token):
+ r1 = None
+ postUrl = settings.EM_REST_URL + "vf/"
+ targetVersion = DBGeneral.select_from(
+ "uuid", "ice_deployment_target", 1)
+ ecompRelease = DBGeneral.select_from("uuid", "ice_ecomp_release", 1)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = 'token ' + token
+ jdata = [{"virtual_function": Helper.rand_string("randomString"),
+ "version": Helper.rand_string("randomString") + Helper.rand_string("randomNumber"),
+ "target_lab_entry_date": time.strftime("%Y-%m-%d"),
+ "target_aic_uuid": targetVersion,
+ "ecomp_release": ecompRelease,
+ "is_service_provider_internal": False}]
+ try:
+ r1 = requests.post(
+ postUrl, json=jdata, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ logger.debug("Virtual Function created successfully!")
+ content = r1.content[1:-1]
+ return content
+ except:
+ if r1 is None:
+ logger.debug("Failed to create VF >>> request failed!")
+ else:
+ logger.debug(
+ "Failed to create VF >>> %s %s \n %s" % (r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def get_engagement(user_content):
+ r1 = None
+ postUrl = settings.EM_REST_URL + 'single-engagement/' + \
+ str(user_content['engagement_uuid'],)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = user_content['session_token']
+ try:
+ r1 = requests.get(
+ postUrl, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ logger.debug("Retrieved the Engagement successfully!")
+ content = r1.content
+ return json.loads(content)
+ except:
+ if r1 is None:
+ logger.debug(
+ "Failed to Retrieve the Engagement >>> request failed!")
+ else:
+ logger.debug(
+ "Failed to Retrieve the Engagement >>> %s %s \n %s" % (r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def invite_team_member(user_content):
+ r1 = None
+ postURL = settings.ICE_EM_URL + '/v1/engmgr/invite-team-members/'
+ logger.debug("Post invite user URL: " + postURL)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = user_content['session_token']
+ data = dict() # Create JSON data for post request.
+ data['email'] = Helper.rand_string(
+ 'randomString') + "@" + ServiceProvider.email
+ data['eng_uuid'] = user_content['engagement_uuid']
+ list_data = []
+ list_data.append(data)
+ try:
+ r1 = requests.post(
+ postURL, json=list_data, headers=headers, verify=False)
+ Helper.internal_assert_boolean(r1.status_code, 200)
+ logger.debug("Invite sent successfully to email " + data['email'])
+ invite_token = DBGeneral.select_where_and("invitation_token", "ice_invitation", "email", data[
+ 'email'], "engagement_uuid", user_content['engagement_uuid'], 1)
+ invite_url = settings.ICE_PORTAL_URL + "/#/signUp?invitation=" + invite_token + \
+ "&email=" + data['email']
+ logger.debug("Invitation URL is: " + invite_url)
+ return data['email'], invite_token, invite_url
+ except:
+ if r1 is None:
+ logger.error("Failed to invite team member.")
+ else:
+ logger.error(
+ "POST request failed to invite team member, see response >>> %s %s" % (r1.status_code, r1.reason))
+ raise
+
+ @staticmethod
+ def add_contact(user_content):
+ r1 = None
+ postURL = settings.ICE_EM_URL + '/v1/engmgr/add-contact/'
+ logger.debug("Post invite vendor contact URL: " + postURL)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = user_content['session_token']
+ data = dict() # Create JSON data for post request.
+ data['company'] = user_content['vendor_uuid']
+ data['email'] = Helper.rand_string(
+ 'randomString') + "@" + ServiceProvider.email
+ data['eng_uuid'] = user_content['engagement_uuid']
+ data['full_name'] = Helper.rand_string('randomString')
+ data['phone_number'] = "+1201" + Helper.rand_string("randomNumber", 6)
+ try:
+ r1 = requests.post(
+ postURL, json=data, headers=headers, verify=False)
+ Helper.internal_assert_boolean(r1.status_code, 200)
+ logger.debug("Invite sent successfully to email " + data['email'])
+ invite_token = DBGeneral.select_where_and("invitation_token", "ice_invitation", "email", data[
+ 'email'], "engagement_uuid", user_content['engagement_uuid'], 1)
+ invite_url = settings.ICE_PORTAL_URL + "/#/signUp?invitation=" + invite_token + \
+ "&email=" + data['email'] + "&full_name=" + data['full_name'] + \
+ "&phone_number=" + \
+ data['phone_number'] + "&company=" + \
+ data['company'] + "&is_contact_user=true"
+ logger.debug("Invitation URL is: " + invite_url)
+ return data['email'], invite_token, invite_url
+ except:
+ if r1 is None:
+ logger.error("Failed to invite vendor contact.")
+ else:
+ logger.error("POST request failed to invite vendor contact, see response >>> %s %s \n %s" % (
+ r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def edit_next_step(user_content, ns_uuid):
+ r1 = None
+ postURL = settings.ICE_EM_URL + '/v1/engmgr/nextsteps/' + ns_uuid + \
+ '/engagement/' + user_content['engagement_uuid'] + '/modify/'
+ logger.debug("Put next step URL: " + postURL)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = user_content['session_token']
+ data = dict() # Create JSON data for post request.
+ data['files'] = []
+ data['assigneesUuids'] = [user_content['uuid']]
+ data['duedate'] = str(datetime.date.today())
+ data['description'] = "API edit next step test " + \
+ Helper.rand_string('randomString')
+ try:
+ r1 = requests.put(
+ postURL, json=data, headers=headers, verify=False)
+ Helper.internal_assert_boolean(r1.status_code, 202)
+ logger.debug("Next step was edited successfully!")
+ except:
+ if r1 is None:
+ logger.error("Failed to edit next step uuid: " + ns_uuid)
+ else:
+ logger.error("Failed to edit next step uuid: " + ns_uuid +
+ ", see response >>> %s %s" % (r1.status_code, r1.reason))
+ raise
+
+ @staticmethod
+ def get_export_dasboard_excel(token, keywords=""):
+ postUrl = settings.EM_REST_URL + \
+ "engagement/export/?stage=All&keyword=" + keywords
+ headers = {"Authorization": token}
+ r1 = requests.get(postUrl, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 200)
+ if (r1.status_code == 200):
+ logger.debug("APIUser activated successfully!")
+ return r1.content
+ else:
+ raise Exception(
+ "Failed to activate user >>> %s %s" % (r1.status_code, r1.reason))
+ return False
+
+ @staticmethod
+ def create_engagement(wait_for_gitlab=True):
+ user_content = APIUser.create_new_user()
+ APIUser.activate_user(
+ user_content['uuid'], user_content['user']['activation_token'])
+ token = APIUser.login_user(user_content['email'])
+ vf_content = json.loads(APIVirtualFunction.create_vf(token))
+ user_content['vfName'] = vf_content['name']
+ user_content['vf_uuid'] = vf_content['uuid']
+ user_content['target_aic'] = vf_content['deployment_target']['version']
+ # <-- ECOMP RELEASE
+ user_content['ecomp_release'] = vf_content[
+ 'ecomp_release']['name']
+ user_content['vnf_version'] = vf_content['version']
+ if(vf_content['vendor']['name'] == "AT&amp;T"):
+ user_content['vendor'] = "AT&T"
+ else:
+ user_content['vendor'] = vf_content['vendor']['name']
+ user_content['vendor_uuid'] = vf_content['vendor']['uuid']
+ user_content['engagement_manual_id'] = vf_content[
+ 'engagement']['engagement_manual_id']
+ user_content['target_lab_entry_date'] = vf_content[
+ 'target_lab_entry_date']
+ user_content['el_email'] = vf_content[
+ 'engagement']['reviewer']['email']
+ user_content['el_name'] = vf_content[
+ 'engagement']['reviewer']['full_name']
+ user_content['pr_email'] = vf_content[
+ 'engagement']['peer_reviewer']['email']
+ user_content['pr_name'] = vf_content[
+ 'engagement']['peer_reviewer']['full_name']
+ user_content['engagement_uuid'] = vf_content['engagement']['uuid']
+ user_content['session_token'] = 'token ' + token
+ user_content['engagement'] = vf_content['engagement']
+ user_content['vfStage'] = vf_content['engagement']['engagement_stage']
+
+ return user_content
+
+ @staticmethod
+ def set_eng_stage(user_content, requested_stage):
+ token = APIUser.login_user(user_content['el_email'])
+ r1 = None
+ putUrl = Constants.Default.URL.Engagement.SingleEngagement.TEXT + \
+ user_content['engagement_uuid'] + "/stage/" + str(requested_stage)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = 'token ' + token
+ try:
+ r1 = requests.put(
+ putUrl, headers=headers, verify=False)
+ Helper.internal_assert(r1.status_code, 202)
+ logger.debug(
+ "Engagement stage was successfully changed to " + str(requested_stage) + "!")
+ content = r1.content[1:-1]
+ return content
+ except:
+ if r1 is None:
+ logger.debug("Failed to set eng stage >>> request failed!")
+ else:
+ logger.debug(
+ "Failed to set eng stage >>> %s %s \n %s" % (r1.status_code, r1.reason, str(r1.content, 'utf-8')))
+ raise
+
+ @staticmethod
+ def update_aic_version(eng_uuid, aic_version_uuid, session_token):
+ r1 = None
+ putURL = Constants.Default.URL.Engagement.EngagementOperations.TEXT + \
+ eng_uuid + '/deployment-targets/' + aic_version_uuid
+ logger.debug("Put next step URL: " + putURL)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = session_token
+ try:
+ r1 = requests.put(putURL, headers=headers, verify=False)
+ Helper.internal_assert_boolean(r1.status_code, 200)
+ logger.debug("AIC version has changed!")
+ except:
+ if r1 is None:
+ msg = "Failed to edit AIC version"
+ else:
+ msg = "Failed to edit AIC version, see response >>> %s %s" % (
+ r1.status_code, r1.reason)
+ raise msg
+
+ @staticmethod
+ def update_ecomp_release(eng_uuid, ecomp_release_uuid, session_token):
+ r1 = None
+ putURL = Constants.Default.URL.Engagement.EngagementOperations.TEXT + \
+ eng_uuid + '/ecomp-releases/' + ecomp_release_uuid
+ logger.debug("Put next step URL: " + putURL)
+ headers = dict() # Create header for post request.
+ headers['Content-type'] = 'application/json'
+ headers['Authorization'] = session_token
+ try:
+ r1 = requests.put(putURL, headers=headers, verify=False)
+ Helper.internal_assert_boolean(r1.status_code, 200)
+ logger.debug("AIC version has changed!")
+ except:
+ if r1 is None:
+ msg = "Failed to update ECOMP release"
+ else:
+ msg = "Failed to update ECOMP release, see response >>> %s %s" % (
+ r1.status_code, r1.reason)
+ raise msg
diff --git a/services/constants.py b/services/constants.py
new file mode 100644
index 0000000..0be529f
--- /dev/null
+++ b/services/constants.py
@@ -0,0 +1,1036 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from django.conf import settings
+
+
+class ServiceProvider:
+ PROGRAM_NAME = "VVP"
+ MainServiceProvider = "ServiceProvider"
+ email = "example.com"
+
+
+class Constants:
+
+ class FEGeneral:
+
+ class CSS:
+ H2 = 'h2'
+
+ class Paths:
+
+ class SSH:
+ PATH = "/root/.ssh/"
+
+ class LocalGitFolder:
+ PATH = "/tmp/git_work/"
+
+ class DBConstants:
+ RETRIES_NUMBER = 120
+
+ class Engagement:
+
+ AIC = 'aic_instantiation_time'
+
+ class Queries:
+ COUNT = "COUNT(*)"
+
+ class IceTables:
+ NOTIFICATION = "ice_notification"
+ USER_PROFILE = "ice_user_profile"
+ ENGAGEMENT = "ice_engagement"
+ CHECKLIST = "ice_checklist"
+ RECENT = "ice_recent_engagement"
+ NEXT_STEP = "ice_next_step"
+
+ class ChecklistStates:
+
+ class Pending:
+ TEXT = "pending"
+
+ class Automation:
+ TEXT = "automation"
+
+ class Review:
+ TEXT = "review"
+
+ class Archive:
+ TEXT = "archive"
+
+ class FEConstants:
+ RETRIES_NUMBER = 120
+
+ class GitLabConstants:
+ RETRIES_NUMBER = 60
+
+ class RGWAConstants:
+ RETRIES_NUMBER = 100
+ BUCKET_RETRIES_NUMBER = 180
+
+ class ChecklistSignalsConstants:
+ RETRIES_NUMBER = 10
+
+ class Users:
+
+ class Admin:
+ EMAIL = "admin@example.com"
+ FULLNAME = "admin bogus user"
+
+ class AdminRO:
+ EMAIL = "admin_ro@example.com"
+
+ class LongEmailLengthStandardUser:
+ EMAIL = "50charslengthemailofstandarduserforinvite@example.com"
+
+ class Toast:
+ ID = "toast-successfully-message"
+ CMS_ID = "announcement-successfully-message"
+ CSS = "html.ng-scope"
+
+ class Cms:
+ Toast_title_id = "toast-title-id"
+ Toast_description = "toast-description"
+ Test_addDT_close_modal_button = "close-modal-button"
+ Documentation = "documentation"
+ Tooltip_title = "tooltip-title"
+ Tooltip_description = "tooltip-description"
+ SearchDocumentation = "search-doc"
+ DocumentationPageContent = ".page-content > p"
+
+ class Template:
+
+ class Heat:
+ TEXT = "Heat Templates"
+
+ class Subtitle:
+
+ class SelectTemplateTitle:
+ TEXT = "please-select"
+
+ class SubmitButton:
+ CSS = "button.btn.btn-primary"
+ ID = "submit-modal"
+
+ class Home:
+
+ class Logo:
+ ID = "logo"
+
+ class Title:
+ ID = "home-heading"
+ TEXT = "Welcome to " + ServiceProvider.PROGRAM_NAME
+
+ class GetStarted:
+ LINK_TEXT = "Get Started"
+ TEXT = "Get Started"
+
+ class Collaborate:
+ ID = "collaborate"
+ XPATH = "//div[3]/div/h3"
+ TEXT = "Collaborate"
+
+ class Validate:
+ XPATH = "//div[2]/div/h3" # FIXME: change xpath
+ TEXT = "Validate"
+
+ class Incubate:
+ # FIXME: change xpath
+ XPATH = "//section[@id='boxes']/div/div/div/h3"
+ TEXT = "Incubate"
+
+ class Login:
+
+ class Signup:
+ LINK_TEXT = "Sign Up"
+
+ class Title:
+ CSS = "h1.ng-binding"
+ TEXT = "Login"
+
+ class SubTitle:
+ CSS = "h2.ng-binding"
+ TEXT = "Please use the form below to login"
+
+ class Email:
+ NAME = "email"
+
+ class Password:
+ NAME = "password"
+
+ class Error:
+ CSS = "div.form-group.has-error > div.ice-form-error > span"
+ TEXT = "Password is a required field."
+
+ class ResetPassword:
+ LINK_TEXT = "Reset your password?"
+ TEXT = "Reset your password?"
+
+ class DontHaveAccount:
+ ID = "id-dont-have-an-account"
+ TEXT = "Don't have an account?"
+
+ class Toast:
+ TEXT = "User or Password does not match"
+
+ class Signup:
+
+ class Title:
+ CSS = "h1.ng-binding"
+ TEXT = "Sign Up"
+
+ class SubTitle:
+ CSS = "h2.ng-binding"
+ TEXT = "Please use the form to Sign Up to " + \
+ ServiceProvider.PROGRAM_NAME
+
+ class Company:
+ NAME = "company"
+
+ class FullName:
+ NAME = "fullname"
+
+ class Email:
+ NAME = "email"
+
+ class Phone:
+ NAME = "phone"
+
+ class Password:
+ NAME = "password"
+
+ class RegularEmail:
+ XPATH = "//input[@type='checkbox']" # FIXME: Change XPath
+
+ class AcceptTerms:
+ XPATH = "(//input[@type='checkbox'])[2]" # FIXME: Change XPath
+
+ class Toast:
+
+ class Captcha:
+ TEXT = "Please fill CAPTCHA!"
+
+ class NotMainVendor:
+ TEXT = "Email address should be with service provider domain for signees that their company =" \
+ + ServiceProvider.MainServiceProvider
+
+ class HaveAccount:
+ LINK_TEXT = "Already have an account?"
+ TEXT = "Already have an account?"
+
+ class ActivateAccount:
+
+ class Title:
+ CSS = "h1.ng-binding"
+ TEXT = "Activate Your Account"
+
+ class SubTitle:
+ CSS = "h2.ng-binding"
+ TEXT = "Please follow the instructions below to activate your account."
+
+ class Toast:
+ TEXT = "Please activate your account first"
+
+ class ResetPassword:
+
+ class Toast:
+
+ class Success:
+ TEXT = "An email with detailed instructions on how to reset your password was sent to your Email."
+
+ class Title:
+ CSS = "h1.ng-binding"
+ TEXT = "Reset Your Password"
+
+ class SubTitle:
+ CSS = "h2.ng-binding"
+ TEXT = "Please follow the instructions below to reset your password"
+
+ class Button:
+ TEXT = "Send Instructions"
+
+ class Email:
+ NAME = "email"
+
+ class UpdatePassword:
+
+ class Title:
+ CSS = "h1.ng-binding"
+ TEXT = "Update Your Password"
+
+ class SubTitle:
+ CSS = "h2.ng-binding"
+ TEXT = "Please follow the instructions below to update your password"
+
+ class Password:
+ NAME = "password"
+
+ class ConfirmPassword:
+ NAME = "confirm_password"
+
+ class Button:
+ TEXT = "Update Password"
+
+ class Toast:
+ TEXT = "Password was updated Successfully!"
+
+ class Dashboard:
+
+ class Modal:
+ TITLE_ID = "modal-title"
+ CLOSE_BUTTON_ID = "close-modal-button"
+
+ class Default:
+ DASHBOARD_ID = "dashboard"
+ STATISTICS = "statistics"
+
+ class Checklist:
+
+ TITLE = "Checklist:"
+
+ class ChecklistDefaultNames:
+ HEAT_TEMPLATES = "Heat Templates"
+ IMAGE_VALIDATION = "Image Validation"
+ AIC_INSTANTIATION = "AIC Instantiation"
+ ASDC_ONBOARDING = "ASDC Onboarding"
+
+ class Name:
+ ID = "cl-name-id"
+
+ class AuditLog:
+ ID = "audit-log"
+
+ class LastLocalAuditLog:
+ CSS = "#audit-log-list > li:last-child p"
+
+ class AuditLogList:
+ ID = "audit-log-list"
+
+ class JenkinsLog:
+
+ ID = "jenkins-log"
+
+ class Modal:
+
+ class Title:
+ ID = "general-log-modal-title-id"
+ TEXT = "Jenkins log"
+
+ class Body:
+ ID = 'general-log-modal-body-id'
+ TEXT_SAMPLE = 'Started by user admin'
+ BUILD_IDENTIFIER = '/bin/sh /tmp/'
+
+ class LineItem:
+
+ class Approve:
+ CSS = "li.approved-cl-btn"
+
+ class Deny:
+ CSS = "li.denied-cl-btn"
+
+ class Approve:
+ pass
+
+ class Reject:
+ ID = "state-actions-btn-reject"
+
+ class Modal:
+
+ class Button:
+ ID = "reject-state"
+ TEXT = "Reject"
+
+ class Comment:
+ NAME = "entry_comment"
+
+ class AddNS:
+ TITLE = "Add Next Steps"
+ ID = "state-actions-btn-add-next-steps"
+ CSS = "span.font_header"
+
+ class GeneralPrompt:
+
+ class UpperTitle:
+ ID = "general-prompt-upper-headline"
+
+ class Title:
+ ID = "general-prompt-title"
+
+ class ApproveButton:
+ ID = "general-prompt-approve-btn"
+
+ class CancelButton:
+ ID = "general-prompt-cancel-btn"
+
+ class Wizard:
+
+ class Open:
+ CSS = "div[modal-animation='true']"
+ CLASS_NAME = "getting-started-wizard"
+
+ class Title:
+ CSS = "h2.modal-title.ng-binding"
+
+ class CloseButton:
+ ID = "close-wizard-button"
+
+ class AddVF:
+
+ class Title:
+ TEXT = "Add a VF"
+
+ class AIC_Version:
+ TEXT = "aic-version"
+
+ class ECOMP_Release:
+ TEXT = "ecomp-release"
+
+ class AddVendorContact:
+
+ class Title:
+ TEXT = "Add Vendor Contact"
+
+ class InviteTeamMembers:
+
+ class Title:
+ NAME = "Invite Team Members"
+ TEXT = "Invite Team Members"
+
+ class Button:
+ TEXT = "Send invitations"
+
+ class AddSSHKey:
+
+ class Title:
+ NAME = "Add SSH Key"
+ TEXT = "Add SSH Key"
+
+ class TextBox:
+ NAME = "key"
+
+ class ActivateMsg:
+
+ class Success:
+ TEXT = "You have successfully activated your account!"
+
+ class Fail:
+ TEXT = "Please activate your account first"
+
+ class Avatar:
+ ID = "avatar"
+
+ class Account:
+ LINK_TEXT = "Account"
+
+ class Title:
+ CSS = "h2.ng-scope"
+ TEXT = "Account"
+
+ class FullName:
+ NAME = "fullname"
+
+ class Email:
+ NAME = "email"
+
+ class Phone:
+ NAME = "phone"
+
+ class Company:
+ NAME = "company"
+
+ class SSHKey:
+ NAME = "ssh_key"
+
+ class UpdateFailed:
+ # TEXT = "Something went wrong while trying to update user account"
+ TEXT = "Updating SSH Key failed due to invalid key."
+
+ class Update:
+
+ class Success:
+ TEXT = "Account was updated successfully!"
+
+ class RGWA:
+
+ class Key:
+ TITLE_ID = "access-key-title"
+ KEY_ID = "access-key-value"
+
+ class Secret:
+ TITLE_ID = "access-secret-title"
+ SECRET_ID = "access-secret-value"
+ BUTTON_ID = "show-access-secret"
+ SECRET_TEXT = "•••••••••••••••"
+
+ class UserProfileSettings:
+ ID = 'user-profile-settings'
+ TitleID = 'user-profile-settings-title'
+ TitleText = 'Settings'
+ ReceiveEmailsID = 'receive-emails'
+ ReceiveNotificationsID = 'receive-notifications'
+ ReceiveEmailEveryTimeID = 'receive-emails-every-time'
+ ReceiveDigestEmailID = 'receive-digest-emails'
+ UpdateButtonID = 'update-account-user-profile-settings'
+
+ class Notifications:
+ LINK_TEXT = "Notifications"
+
+ class NotificationColumn:
+ ID = "table-col-"
+
+ class DeleteNotification:
+ ID = "del-notification-"
+
+ class Count:
+ ID = "notifications-count"
+ RETRIES_NUMBER = 20
+
+ class Title:
+ ID = "notifications"
+ TEXT = "Notifications"
+
+ class Admin:
+ LINK_TEXT = "Admin"
+
+ class Title:
+ CSS = "h1.caption"
+ TEXT = "Admin"
+ ID = "admin-toolbar-link"
+
+ class Logout:
+ LINK_TEXT = "Logout"
+
+ class Feedback:
+ ID = "feedback-toolbar-link"
+
+ class FeedbackModal:
+ SAVE_BTN_ID = "add-feedback-save-button"
+
+ class Statuses:
+ ID = "logo"
+
+ class Body:
+ ID = "search-results"
+ TEXT = "Export to Excel >>"
+
+ class Title:
+ ID = "dashboard-title"
+ TEXT = "Statuses"
+
+ class FilterDropdown:
+ ID = "search-filter-stage"
+
+ class SearchBox:
+ ID = "search-filter-keyword"
+
+ class SearchFilters:
+ ID = "search-filters"
+
+ class AssignedNS:
+ ID = "next-steps-header"
+
+ class Statistics:
+
+ class Title:
+ ID = "statistics-header"
+ TEXT = "Statistics"
+
+ class FilterDropdown:
+ CSS = "#statistics-header > .search-filters > .search-filter-stage"
+
+ class ValidationsNumber:
+ ID = "id-validations-num"
+
+ class EngagementsNumber:
+ ID = "id-engagements-num"
+
+ class News:
+
+ class Title:
+ ID = "news-and-announcements-header"
+ TEXT = "News & Announcements"
+
+ class List:
+ ID = "news-and-announcements-list"
+ TEXT = "There are no posts."
+
+ class ExportExcel:
+ ID = "export-to-csv"
+ TEXT = "Export to Excel >>"
+
+ class Overview:
+
+ class AdminDropdown:
+ ID = "admin-actions-dropdown"
+
+ class ArchiveEngagement:
+ LINK_TEXT = "Archive"
+
+ class Wizard:
+
+ class Title:
+ ID = "archive-engagement-title"
+ TEXT = "Archive Engagement"
+
+ class Reason:
+ NAME = "reason"
+
+ class ChangeReviewer:
+ LINK_TEXT = "Change Reviewer"
+
+ class Wizard:
+
+ class Title:
+ ID = "archive-engagement-title"
+ TEXT = "Select Engagement Lead"
+
+ class Select:
+ NAME = "selected-user"
+
+ class Toast:
+ TEXT = "Reviewer updated successfully."
+
+ class ChangePeerReviewer:
+ LINK_TEXT = "Change Peer Reviewer"
+
+ class Wizard:
+
+ class Title:
+ ID = "archive-engagement-title"
+ TEXT = "Select Engagement Lead"
+
+ class Toast:
+ TEXT = "Peer reviewer updated successfully."
+
+ class UpdateStatus:
+ LINK_TEXT = "Update Status"
+ PROGRESS = "progress"
+ PROGRESS_CSS = 'input[name="progress"]'
+ TARGET = 'vm.engagement.target_completion_date'
+ HEAT = 'vm.engagement.heat_validated_time'
+ IMAGE_SACN = 'vm.engagement.image_scan_time'
+ AIC = 'vm.engagement.aic_instantiation_time'
+ ASDC = 'vm.engagement.asdc_onboarding_time'
+ STATUS = "status"
+ SUBMIT = 'button[type="submit"]'
+ SUCCESS_MSG = 'Engagement status updated successfully.'
+
+ class BucketURL:
+ ID = "bucket-url"
+ TEXT = "STORAGE BUCKET: "
+
+ class GitURL:
+ ID = "git-url"
+
+ class Title:
+ ID = "engagement-title"
+
+ class Star:
+ ID = "star-engagement-action"
+
+ class Stage:
+
+ class Approve:
+ XPATH = "//button[@type='submit']" # FIXME: Change XPath
+
+ class Deny:
+ # FIXME: Change XPath
+ XPATH = "(//button[@type='submit'])[2]"
+
+ class Set:
+ ID = "set-stage-"
+
+ class Progress:
+
+ class ValidationsDates:
+
+ AIC_ID = 'aic-instantiation-time'
+ HEAT_ID = 'heat-validated-time'
+ IMAGE_ID = 'image-scan-time'
+ ASDC_ID = 'asdc-onboarding-time'
+ VALIDATION_DATES_ARRAY = [
+ AIC_ID, HEAT_ID, IMAGE_ID, ASDC_ID]
+
+ class VnfVersion:
+ CLASS = "vnf_version_value"
+
+ class Percent:
+ ID = "progress-percentage"
+ TEXT = "0 %"
+
+ class Change:
+ ID = "edit-change-progress"
+ NUMBER = "55"
+ TEXT = "55 %"
+
+ class Wizard:
+ NAME = "progress"
+
+ class Title:
+ TEXT = "Specify Progress in %"
+
+ class Button:
+ TEXT = "Save"
+
+ class Status:
+
+ class Header:
+ ID = "#engagement-status-header > span"
+
+ class Add:
+ CSS = "i.add-engagement-status"
+
+ class Edit:
+ CSS = "i.edit-engagement-status"
+
+ class Description:
+ ID = "status-description"
+
+ class LastUpdated:
+ ID = "status-update-details"
+
+ class TeamMember:
+ ID = "team-members-plus-button-id"
+ MEMBER_ID = "team-member-%s"
+
+ class Title:
+ ID = "team-member-title"
+
+ class RemoveUser:
+ ID = "remove-member"
+
+ class Title:
+ TEXT = "Remove user from engagement team: %s"
+
+ class Message:
+ TEXT = "Are you sure you would like to remove the user out of the team members?"
+
+ class NextSteps:
+
+ class FilterByFileDropDown:
+ ID = "selected-file-filter-dropdown"
+ ANY_FILE_LINK_TEXT = "Any file"
+ FILE0_LINK_TEXT = "file0.yaml"
+ FILE1_LINK_TEXT = "file1.yaml"
+ FILE2_LINK_TEXT = "file2.yaml"
+
+ class StateDropDown:
+ ID = "selected-state-filter-dropdown"
+ INCOMPLETE_LINK_TEXT = "Incomplete"
+ COMPLETED_LINK_TEXT = "Completed"
+
+ class Add:
+ TITLE = "Engagement:"
+ ID = "add-next-step-button"
+
+ class Title:
+ CSS = "h2"
+ TEXT = "Add Next Steps"
+
+ class Description:
+ ID = "description"
+ STEP_DESC_ID = "step-description-"
+
+ class Button:
+ TEXT = "Submit Next Steps"
+
+ class AssociatedFiles:
+ ID = "associated-files-list"
+ ALL_FILES_SELECTED = "3 files selected"
+ SELECT_ALL_FILES_NAME = "Select All"
+
+ class AssociatedFiles:
+ ID = "associated-files"
+ EmptyMsgID = "associated-files-empty-msg"
+ EmptyMsg = "There are no files for this next step"
+ FileId = "file0"
+
+ class DetailedView:
+ ID = "detailed-view-"
+
+ class DeploymentTarget:
+ ID = "deployment-targets"
+ TEXT = "Deployment Targets"
+ TITLE = "Add Deployment Target"
+ SAVE = "add-dt-save-button"
+ CSS = "span.col-md-10.ng-binding"
+ ID_REMOVE_DTS = "remove-dts-"
+
+ class AddDeploymentTargetButton:
+ ID = "add-dt"
+
+ class VirtualFunctionComponents:
+ ID = "virtual-function-components"
+ TEXT = "Virtual Function Components"
+
+ class ValidationDetails:
+ PLUS = "update-validation-details"
+ TITLE = "Validation Details (ECOMP, AIC, VF Version)"
+ SAVE = "edit-validation-setails-save-button"
+ ID = "vd-title"
+ TEXT = "Validation Details"
+
+ class TargetAICVersion:
+ ID = "target-aic-version-headline"
+ TEXT = "Target AIC Version:"
+ AIC3 = "AIC 3.0"
+
+ class ECOMPRelease:
+ ID = "ecomp-release-headline"
+ TEXT = "ECOMP Release:"
+ ID_ECOMP = "ecomp-select-options-"
+ UNKNOW = "Unknown"
+
+ class VFVersion:
+ ID = "vf-version-headline"
+ TEXT = "VF Version:"
+ ID_VERSION = "id-vf-version"
+ VF_VERSION_ID = "vf_version_"
+
+ class TargetLabEntry:
+ ID = "target-lab-entry"
+ TEXT = "Target Lab Entry"
+ CSS = "#target-lab-entry-header > span"
+ CHANGE = "change-lab-entry-date"
+ INPUT_CSS = '.md-datepicker-input'
+ CONTENT_CSS = "h4.target-lab-entry-content"
+
+ class Add:
+ ID = "add-dt"
+
+ class VFC:
+ TEXT = "Virtual Function Components"
+ ID = "visible-dts-"
+
+ class Add:
+ ID = "add-vfc"
+
+ class Remove:
+ ID = "remove-vfc-"
+
+ class Save_button:
+ ID = "add-vfc-save-button"
+
+ class Choose_Company:
+ ID = "add-vfc-choose-company"
+
+ class AIC:
+ TEXT = "Target AIC Version"
+ ID = "aic_version_"
+
+ class Edit:
+ ID = "test_AIC_Version_Edit"
+
+ class Confirm:
+ ID = "test_AIC_Version_Update"
+
+ class Decline:
+ ID = "test_AIC_Version_Remove"
+
+ class Dropdown:
+ ID = "aic-version-select"
+
+ class TwoPointFive:
+ ID = "aic_select_options_2.5"
+ TEXT = "2.5"
+
+ class Three:
+ ID = "aic_select_options_3.0"
+ TEXT = "3.0"
+
+ class ThreePointFive:
+ ID = "aic_select_options_3.5"
+ TEXT = "3.5"
+
+ class Four:
+ ID = "aic_select_options_4.0"
+ TEXT = "4.0"
+
+ class UniversalVersion:
+ ID = "aic_select_options_%s"
+
+ class NoVersion:
+ ID = "aic_select_options_No version number available"
+ TEXT = "No version number available"
+
+ class ECOMP:
+ ID = "ecomp_version_"
+
+ class Edit:
+ ID = "test_ECOMP_Release_Edit"
+
+ class Confirm:
+ ID = "test_ECOMP_Release_Update"
+
+ class Decline:
+ ID = "test_ECOMP_Release_Remove"
+
+ class Dropdown:
+ ID = "ecomp-release-select"
+
+ class Unknown:
+ ID = "ecomp-select-options-Unknown"
+
+ class UniversalRelease:
+ ID = "ecomp-select-options-%s"
+
+ class LeftPanel:
+
+ class Title:
+ CSS = "h1.caption"
+ TEXT = "Engagements"
+
+ class AddEngagement:
+ ID = "add-engagement"
+
+ class SearchBox:
+ ID = "search-eng"
+
+ class Results:
+ ID = "search-%s" # %s --> VF name
+ CSS = "span.search-engagement-name.ng-binding"
+ XPATH = "//input[@type='text']"
+
+ class NoResults:
+ ID = "search-no-results"
+
+ class CreateChecklist:
+ ID = "btn-create-checklist" # "btn-modal-update-checklist"
+
+ class EditChecklistTemplate:
+ SUCCESS_SAVE_MSG = "Template was saved successfully."
+ SAVE_BTN = "Save"
+ HEAT = "Editing Heat"
+ SAVE_BTN_ID = "save-button"
+ APPROVE_BTN_ID = "general-prompt-approve-btn"
+ SUCCESS_ID = "toast-successfully-message"
+ APPROVE_BTN_TITLE_ID = "general-prompt-title"
+ APPROVE_BTN_TITLE_TEXT = "Are you done editing?"
+ CL_TEMPLATE_SAVED_TXT = "Template was saved successfully."
+ FIRST_SECTION_ID = "edit-section-btn-0"
+ FIRST_SECTION_INPUT_ID = "edit-section-input-0"
+ REJECT_BTN_ID = "state-actions-btn-reject"
+ ADD_LINE_ITEM_BTN = "add-lineitem-btn"
+ EDIT_LINE_ITEM_BTN = "edit-lineitem-btn"
+ EDIT_LINE_ITEM_NAME = "edit-line-item-name-input"
+ LINE_ITEM_DESC_TEXT_BOX = "edit-lineitem-description"
+ EDIT_LINE_ITEM_DESC = "edit-lineitem-description-input"
+ FIRST_LINE_ITEM_ID = "select-lineitem-btn-0.0"
+ WYSIWYG_BUTTON_BOLD = "//button[@type='button']"
+ DASHBOARD_ID = "dashboard"
+ SEARCH_ENG_ID = "search-eng"
+ DELETE_LINE_ITEM = "delete-lineitem-btn"
+
+ class DefaultChecklistTemplateParametrs:
+ DEFAULT_FIRST_SECTION_VALUE = "External References"
+
+ class EngagementStages:
+ INTAKE = "Intake"
+ ACTIVE = "Active"
+ VALIDATED = "Validated"
+ COMPLETED = "Completed"
+ ALL = "All"
+
+ class Default:
+
+ class TestPrefix:
+ Test = "test_"
+ Center = "center-"
+
+ class Password:
+ TEXT = "iceusers"
+
+ class NewPass:
+ TEXT = "1234"
+
+ class Phone:
+ TEXT = "+972-50-555-5555"
+
+ class LoginURL:
+ TEXT = settings.ICE_PORTAL_URL + "/#/login"
+
+ class DashbaordURL:
+ TEXT = settings.ICE_PORTAL_URL + "/#/dashboard/dashboard"
+
+ class OverviewURL:
+ TEXT = settings.ICE_PORTAL_URL + "/#/dashboard/overview"
+
+ class InviteURL:
+
+ class Login:
+ TEXT = settings.ICE_PORTAL_URL + "/#/login?invitation="
+
+ class Signup:
+ TEXT = settings.ICE_PORTAL_URL + "/#/signUp?eng_uuid="
+
+ class URL:
+
+ class Engagement:
+
+ class EngagementOperations:
+ TEXT = settings.ICE_EM_URL + '/v1/engmgr/engagement/'
+
+ class SingleEngagement:
+ TEXT = settings.ICE_EM_URL + \
+ '/v1/engmgr/single-engagement/'
+
+ class Checklist:
+ TEXT = settings.ICE_EM_URL + '/v1/engmgr/engagement/'
+
+ class Get:
+ TEXT = settings.ICE_EM_URL + '/v1/engmgr/checklist/'
+
+ class Create:
+ TEXT = settings.ICE_EM_URL + '/v1/engmgr/checklist/'
+
+ class Update:
+ TEXT = settings.ICE_EM_URL + '/v1/engmgr/checklist/'
+
+ class Rest:
+ TEXT = settings.EM_REST_URL + "checklist/"
+
+ class GitLab:
+
+ class Projects:
+ TEXT = settings.GITLAB_URL + "api/v3/projects/"
+
+ class Users:
+ TEXT = settings.GITLAB_URL + "api/v3/users/"
+
+ class BlockUI:
+ CSS = "div.block-ui-message.ng-binding"
diff --git a/services/database/__init__.py b/services/database/__init__.py
new file mode 100644
index 0000000..30d7152
--- /dev/null
+++ b/services/database/__init__.py
@@ -0,0 +1,38 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
diff --git a/services/database/__pycache__/__init__.cpython-36.pyc b/services/database/__pycache__/__init__.cpython-36.pyc
new file mode 100644
index 0000000..12ed104
--- /dev/null
+++ b/services/database/__pycache__/__init__.cpython-36.pyc
Binary files differ
diff --git a/services/database/__pycache__/db_bridge.cpython-36.pyc b/services/database/__pycache__/db_bridge.cpython-36.pyc
new file mode 100644
index 0000000..06fb01e
--- /dev/null
+++ b/services/database/__pycache__/db_bridge.cpython-36.pyc
Binary files differ
diff --git a/services/database/__pycache__/db_checklist.cpython-36.pyc b/services/database/__pycache__/db_checklist.cpython-36.pyc
new file mode 100644
index 0000000..81e29bd
--- /dev/null
+++ b/services/database/__pycache__/db_checklist.cpython-36.pyc
Binary files differ
diff --git a/services/database/__pycache__/db_cms.cpython-36.pyc b/services/database/__pycache__/db_cms.cpython-36.pyc
new file mode 100644
index 0000000..783d2f8
--- /dev/null
+++ b/services/database/__pycache__/db_cms.cpython-36.pyc
Binary files differ
diff --git a/services/database/__pycache__/db_general.cpython-36.pyc b/services/database/__pycache__/db_general.cpython-36.pyc
new file mode 100644
index 0000000..c39ce12
--- /dev/null
+++ b/services/database/__pycache__/db_general.cpython-36.pyc
Binary files differ
diff --git a/services/database/__pycache__/db_user.cpython-36.pyc b/services/database/__pycache__/db_user.cpython-36.pyc
new file mode 100644
index 0000000..46d136e
--- /dev/null
+++ b/services/database/__pycache__/db_user.cpython-36.pyc
Binary files differ
diff --git a/services/database/__pycache__/db_virtual_function.cpython-36.pyc b/services/database/__pycache__/db_virtual_function.cpython-36.pyc
new file mode 100644
index 0000000..8a46fb8
--- /dev/null
+++ b/services/database/__pycache__/db_virtual_function.cpython-36.pyc
Binary files differ
diff --git a/services/database/db_bridge.py b/services/database/db_bridge.py
new file mode 100644
index 0000000..fc765c7
--- /dev/null
+++ b/services/database/db_bridge.py
@@ -0,0 +1,60 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+class DBBridge:
+
+ """
+ This class helps to use functions inside classes with circular import (dependencies).
+ Use this class only when there is circular import in one of the DB services.
+ """
+
+ @staticmethod
+ def select_personal_next_step(user_email):
+ """select_personal_next_step: Originally can be found under DBUser class."""
+ from services.database.db_user import DBUser
+ return DBUser.select_personal_next_step(user_email)
+
+ @staticmethod
+ def helper_rand_string(type, num=""):
+ from services.helper import Helper
+ return Helper.rand_string(type, num)
+
+ @staticmethod
+ def helper_internal_assert(arg1, arg2):
+ from services.helper import Helper
+ return Helper.internal_assert(arg1, arg2)
diff --git a/services/database/db_checklist.py b/services/database/db_checklist.py
new file mode 100644
index 0000000..15851cf
--- /dev/null
+++ b/services/database/db_checklist.py
@@ -0,0 +1,386 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import time
+from uuid import uuid4
+
+from django.utils import timezone
+import psycopg2
+
+from services.constants import Constants
+from services.database.db_general import DBGeneral
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class DBChecklist:
+
+ @staticmethod
+ def select_where_approval_state(queryColumnName, queryTableName, whereParametrType, whereParametrValue, fetchNum):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "select %s from %s Where %s = '%s' and state = 'approval';" % (
+ queryColumnName, queryTableName, whereParametrType, whereParametrValue)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ if (fetchNum == 0):
+ result = str(cur.fetchall())
+ elif (fetchNum == 1):
+ result = str(cur.fetchone())
+ if(result.find("',)") != -1): # formatting strings e.g uuid
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ dbConn.close()
+ logger.debug("Query result: " + str(result))
+ if result == None:
+ errorMsg = "select_where_approval_state FAILED "
+ logger.error(errorMsg)
+ raise
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_where_approval_state FAILED "
+ raise Exception(errorMsg, "select_where_approval_state FAILED")
+
+ @staticmethod
+ def select_where_pr_state(queryColumnName, queryTableName, whereParametrType, whereParametrValue, fetchNum):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "select %s from %s Where %s = '%s' and state = 'peer_review';" % (
+ queryColumnName, queryTableName, whereParametrType, whereParametrValue)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ if (fetchNum == 0):
+ result = str(cur.fetchall())
+ elif (fetchNum == 1):
+ result = str(cur.fetchone())
+ if(result.find("',)") != -1): # formatting strings e.g uuid
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ dbConn.close()
+ if result == None:
+ errorMsg = "select_where_pr_state FAILED "
+ logger.error(errorMsg)
+ raise
+ logger.debug("Query result: " + str(result))
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_where FAILED "
+ raise Exception(errorMsg, "select_where")
+
+ @staticmethod
+ def select_where_cl_not_archive(queryColumnName, queryTableName, whereParametrType, whereParametrValue, fetchNum):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "select %s from %s Where %s = '%s' and state != 'archive';" % (
+ queryColumnName, queryTableName, whereParametrType, whereParametrValue)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ if (fetchNum == 0):
+ result = str(cur.fetchall())
+ elif (fetchNum == 1):
+ result = str(cur.fetchone())
+ if(result.find("',)") != -1): # formatting strings e.g uuid
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ dbConn.close()
+ logger.debug("Query result: " + str(result))
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_where FAILED "
+ raise Exception(errorMsg, "select_where")
+
+ @staticmethod
+ def select_native_where(queryColumnName, queryTableName, whereParametrType, whereParametrValue, fetchNum):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "select %s from %s Where %s = '%s';" % (
+ queryColumnName, queryTableName, whereParametrType, whereParametrValue)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ if (fetchNum == 0):
+ result = str(cur.fetchall())
+ elif (fetchNum == 1):
+ result = str(cur.fetchone())
+ if(result.find("',)") != -1): # formatting strings e.g uuid
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ dbConn.close()
+ logger.debug("Query result: " + str(result))
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_where FAILED "
+ raise Exception(errorMsg, "select_where")
+
+ @staticmethod
+ def update_checklist_to_review_state(queryTableName):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "UPDATE ice_checklist SET state='review' Where name= '%s' and state= 'pending';" % (
+ queryTableName)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ dbConn.commit()
+ dbConn.close()
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "Could not Update User"
+ raise Exception(errorMsg, "Update")
+
+ @staticmethod
+ def update_all_decisions_to_approve(whereParametrValue):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "UPDATE ice_checklist_decision SET review_value='approved' , peer_review_value='approved' Where checklist_id = '%s';" % (
+ whereParametrValue)
+ logger.debug(queryStr)
+ cur.execute(queryStr)
+ dbConn.commit()
+ logger.debug("Query : " + queryStr)
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Could not Update User"
+ logger.debug(e)
+ raise Exception(errorMsg, "Update")
+ finally:
+ dbConn.close()
+
+ @staticmethod
+ def is_archive(checklistName):
+ try:
+ result = False
+ # Fetch all AT&T user ID.
+ checklist_ids = DBGeneral.select_where(
+ "uuid", "ice_checklist", "name", checklistName, 0)
+# checklist_ids = DBGeneral.list_format(checklist_ids)
+ for checklist_id in checklist_ids: # Second Example
+ if isinstance(checklist_id, tuple):
+ checklist_id = checklist_id[0]
+ state = DBGeneral.select_where(
+ "state", "ice_checklist", "uuid", checklist_id, 1)
+ if state == "archive":
+ result = True
+ break
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "is_archive FAILED "
+ raise Exception(errorMsg, "is_archive")
+
+ @staticmethod
+ def get_pr_email(checklistUuid):
+ try:
+ # Fetch one AT&T user ID.
+ owner_id = DBChecklist.select_where_pr_state(
+ "owner_id", "ice_checklist", "uuid", checklistUuid, 1)
+ engLeadEmail = DBGeneral.select_where(
+ "email", "ice_user_profile", "id", owner_id, 1)
+ logger.debug("get_pr_email = " + engLeadEmail)
+ return engLeadEmail
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "get_pr_email FAILED " + str(e)
+ raise Exception(errorMsg, "get_pr_email")
+
+ @staticmethod
+ def get_admin_email(checklistUuid):
+ try:
+ owner_id = DBChecklist.select_where_approval_state(
+ "owner_id", "ice_checklist", "uuid", checklistUuid, 1) # Fetch one AT&T user ID.
+ engLeadEmail = DBGeneral.select_where(
+ "email", "ice_user_profile", "id", owner_id, 1)
+ logger.debug("get_admin_email = " + engLeadEmail)
+ return engLeadEmail
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "get_admin_email FAILED "
+ raise Exception(errorMsg, "get_admin_email")
+
+ @staticmethod
+ def get_owner_email(checklistUuid):
+ try:
+ # Fetch one AT&T user ID.
+ owner_id = DBChecklist.select_native_where(
+ "owner_id", "ice_checklist", "uuid", checklistUuid, 1)
+ engLeadEmail = DBGeneral.select_where(
+ "email", "ice_user_profile", "id", owner_id, 1)
+ logger.debug("getPreeReviewerEngLeadEmail = " + engLeadEmail)
+ return engLeadEmail
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "get_admin_email FAILED "
+ raise Exception(errorMsg, "get_owner_email")
+
+ @staticmethod
+ def update_decisions(checklistUuid, checklistName):
+ checklistTempid = DBGeneral.select_where(
+ "template_id", "ice_checklist", "name", checklistName, 1)
+ checklistLineItems = DBGeneral.select_where_and(
+ "uuid", "ice_checklist_line_item", "line_type", "auto", "template_id", checklistTempid, 0)
+ for lineItem in checklistLineItems:
+ setParametrType2 = "peer_review_value"
+ setParametrValue2 = "approved"
+ whereParametrType2 = "lineitem_id"
+ whereParametrValue2 = lineItem
+ DBGeneral.update_where_and("ice_checklist_decision", "review_value", checklistUuid, "approved",
+ "checklist_id", setParametrType2, setParametrValue2, whereParametrType2, whereParametrValue2)
+
+ @staticmethod
+ def checkChecklistIsUpdated():
+ query = "select uuid from ice_checklist_section where template_id in (select template_id from ice_checklist_template where name='{template_name}') and name='{section_name}'".format(
+ template_name=Constants.Dashboard.LeftPanel.EditChecklistTemplate.HEAT, section_name=Constants.Dashboard.LeftPanel.EditChecklistTemplate.HEAT)
+ return DBGeneral.select_query(query)
+
+ @staticmethod
+ def fetchEngByVfName(vfName):
+ # Fetch one AT&T user ID.
+ return DBGeneral.select_where("engagement_id", "ice_vf", "name", vfName, 1)
+
+ @staticmethod
+ def fetchEngManIdByEngUuid(engagement_id):
+ return DBGeneral.select_where("engagement_manual_id", "ice_engagement", "uuid", engagement_id, 1)
+
+ @staticmethod
+ def fetchChecklistByName(checklistName):
+ query = "select uuid from ice_checklist where name='{cl_name}'".format(
+ cl_name=checklistName)
+ return DBGeneral.select_query(query)
+
+ @staticmethod
+ def create_default_heat_teampleate():
+ template_query = "INSERT INTO public.ice_checklist_template(uuid, name, category, version, create_time)"\
+ "VALUES ('%s', '%s', '%s', '%s', '%s');" % (
+ str(uuid4()), 'Editing Heat', 'first category', '1', timezone.now())
+ DBGeneral.insert_query(template_query)
+ template_id = DBGeneral.select_query(
+ "SELECT uuid FROM public.ice_checklist_template where name = 'Editing Heat'")
+ # SECTIONS
+ section1_query = "INSERT INTO public.ice_checklist_section(uuid, name, weight, description, validation_instructions, create_time, template_id) "\
+ "VALUES ('%s', '%s', '%s', '%s', '%s','%s', '%s');" % (str(uuid4()), 'External References',
+ '1', 'section descripyion', 'valid instructions', timezone.now(), template_id)
+ DBGeneral.insert_query(section1_query)
+ section1_id = DBGeneral.select_query(
+ ("""SELECT uuid FROM public.ice_checklist_section where name = 'External References' and template_id = '{s}'""").format(s=template_id))
+ section2_query = "INSERT INTO public.ice_checklist_section(uuid, name, weight, description, validation_instructions, create_time, template_id) "\
+ "VALUES ('%s', '%s', '%s', '%s', '%s','%s', '%s');" % (str(uuid4()), 'Parameter Specification',
+ '2', 'section descripyion', 'valid instructions', timezone.now(), template_id)
+ DBGeneral.insert_query(section2_query)
+ section2_id = DBGeneral.select_query(
+ ("""SELECT uuid FROM public.ice_checklist_section where name = 'Parameter Specification' and template_id = '{s}'""").format(s=template_id))
+ # Line items
+ line_item1 = "INSERT INTO public.ice_checklist_line_item(uuid, name, weight, description, line_type, validation_instructions,create_time,section_id, template_id) "\
+ "VALUES ('%s', '%s', '%s', '%s', '%s','%s', '%s', '%s', '%s');" % (str(uuid4()), 'Normal references', '1', 'Numeric parameters should include range and/or allowed values.', 'manual',
+ 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', timezone.now(), section1_id, template_id)
+ DBGeneral.insert_query(line_item1)
+ line_item2 = "INSERT INTO public.ice_checklist_line_item(uuid, name, weight, description, line_type, validation_instructions,create_time, section_id, template_id) "\
+ "VALUES ('%s', '%s', '%s', '%s', '%s','%s', '%s', '%s', '%s');" % (str(uuid4()), 'String parameters', '2', 'Numeric parameters should include range and/or allowed values.', 'auto',
+ 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', timezone.now(), section2_id, template_id)
+ DBGeneral.insert_query(line_item2)
+ line_item3 = "INSERT INTO public.ice_checklist_line_item(uuid, name, weight, description, line_type, validation_instructions,create_time,section_id, template_id) "\
+ "VALUES ('%s', '%s', '%s', '%s', '%s','%s', '%s', '%s', '%s');" % (str(uuid4()), 'Numeric parameters', '3', 'Numeric parameters should include range and/or allowed values.', 'manual',
+ 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', timezone.now(), section2_id, template_id)
+ DBGeneral.insert_query(line_item3)
+ line_item4 = "INSERT INTO public.ice_checklist_line_item(uuid, name, weight, description, line_type, validation_instructions,create_time, section_id, template_id) "\
+ "VALUES ('%s', '%s', '%s', '%s', '%s','%s', '%s', '%s', '%s');" % (str(uuid4()), 'VF image', '2', 'Numeric parameters should include range and/or allowed values.', 'auto',
+ 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', timezone.now(), section1_id, template_id)
+ DBGeneral.insert_query(line_item4)
+ line_item5 = "INSERT INTO public.ice_checklist_line_item(uuid, name, weight, description, line_type, validation_instructions,create_time,section_id, template_id) "\
+ "VALUES ('%s', '%s', '%s', '%s', '%s','%s', '%s', '%s', '%s');" % (str(uuid4()), 'Parameters', '1', 'Numeric parameters should include range and/or allowed values.', 'auto',
+ 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', timezone.now(), section2_id, template_id)
+ DBGeneral.insert_query(line_item5)
+
+ @staticmethod
+ def create_editing_cl_template_if_not_exist():
+ template_id = DBGeneral.select_query(("""SELECT uuid FROM public.ice_checklist_template where name = '{s}'""").format(
+ s=Constants.Dashboard.LeftPanel.EditChecklistTemplate.HEAT))
+ if template_id == 'None':
+ DBChecklist.create_default_heat_teampleate()
+ session.createTemplatecount = True
+
+ @staticmethod
+ def state_changed(identify_field, field_value, expected_state):
+ get_state = str(DBGeneral.select_where(
+ "state", Constants.DBConstants.IceTables.CHECKLIST, identify_field, field_value, 1))
+ counter = 0
+ while get_state != expected_state and counter <= Constants.DBConstants.RETRIES_NUMBER:
+ time.sleep(session.wait_until_time_pause_long)
+ logger.debug("Checklist state not changed yet , expecting state: %s, current result: %s (attempt %s of %s)" % (
+ expected_state, get_state, counter, Constants.DBConstants.RETRIES_NUMBER))
+ counter += 1
+ get_state = str(DBGeneral.select_where(
+ "state", Constants.DBConstants.IceTables.CHECKLIST, identify_field, field_value, 1))
+
+ if get_state == expected_state:
+ logger.debug("Checklist state was successfully changed into: " +
+ expected_state + ", and was verified over the DB")
+ return expected_state
+ raise Exception(
+ "Expected checklist state never arrived " + expected_state, get_state)
+
+ @staticmethod
+ def get_recent_checklist_uuid(name):
+ required_uuid = DBGeneral.select_where_not_and_order_by_desc(
+ 'uuid', Constants.DBConstants.IceTables.CHECKLIST, 'name', name, 'state', Constants.ChecklistStates.Archive.TEXT, 'create_time')
+ return required_uuid
diff --git a/services/database/db_cms.py b/services/database/db_cms.py
new file mode 100644
index 0000000..3c2b2c6
--- /dev/null
+++ b/services/database/db_cms.py
@@ -0,0 +1,265 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import psycopg2
+from wheel.signatures import assertTrue
+
+from services.constants import Constants
+from services.database.db_general import DBGeneral
+from services.frontend.base_actions.click import Click
+from services.frontend.base_actions.enter import Enter
+from services.frontend.base_actions.wait import Wait
+from services.frontend.fe_dashboard import FEDashboard
+from services.frontend.fe_general import FEGeneral
+from services.frontend.fe_user import FEUser
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+
+class DBCMS:
+
+ @staticmethod
+ def insert_query(queryStr):
+ try:
+ nativeIceDb = psycopg2.connect(
+ DBGeneral.return_db_native_connection('cms_db'))
+ dbConn = nativeIceDb
+ cur = dbConn.cursor()
+ logger.debug("Query: " + queryStr)
+ cur.execute(queryStr)
+ dbConn.commit()
+ dbConn.close()
+ logger.debug("Insert query success!")
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ raise Exception("Couldn't fetch answer using the given query.")
+
+ @staticmethod
+ def update_query(queryStr):
+ try:
+ nativeIceDb = psycopg2.connect(
+ DBGeneral.return_db_native_connection('cms_db'))
+ dbConn = nativeIceDb
+ cur = dbConn.cursor()
+ logger.debug("Query: " + queryStr)
+ cur.execute(queryStr)
+ dbConn.commit()
+ dbConn.close()
+ logger.debug("Update query success!")
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ raise Exception("Couldn't fetch answer using the given query.")
+
+ @staticmethod
+ def select_query(queryStr):
+ try:
+ nativeIceDb = psycopg2.connect(
+ DBGeneral.return_db_native_connection('cms_db'))
+ dbConn = nativeIceDb
+ cur = dbConn.cursor()
+ logger.debug("Query: " + queryStr)
+ cur.execute(queryStr)
+ result = str(cur.fetchone())
+ if(result.find("',)") != -1): # formatting strings e.g uuid
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ dbConn.close()
+ logger.debug("Query result: " + str(result))
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ raise Exception("Couldn't fetch answer using the given query.")
+
+ @staticmethod
+ def get_cms_category_id(categoryName):
+ logger.debug("Get DBCMS category id for name: " + categoryName)
+ queryStr = "SELECT id FROM public.blog_blogcategory WHERE title = '%s' LIMIT 1;" % (
+ categoryName)
+ logger.debug("Query : " + queryStr)
+ result = DBCMS.select_query(queryStr)
+ return result
+
+ @staticmethod
+ def insert_cms_new_post(title, description, categoryName):
+ logger.debug("Insert new post : " + title)
+ queryStr = "INSERT INTO public.blog_blogpost" \
+ "(comments_count, keywords_string, rating_count, rating_sum, rating_average, title, slug, _meta_title, description, gen_description, created, updated, status, publish_date, expiry_date, short_url, in_sitemap, content, allow_comments, featured_image, site_id, user_id) "\
+ "VALUES (0, '', 0, 0, 0, '%s', '%s-slug', '', '%s', true, current_timestamp - interval '1 day', current_timestamp - interval '2 day', 2, current_timestamp - interval '1 day', NULL, '', true, '<p>%s</p>', true, '', 1, 1);" % (
+ title, title, description, description)
+ logger.debug("Query : " + queryStr)
+ DBCMS.insert_query(queryStr)
+ post_id = DBCMS.get_last_added_post_id()
+ categoryId = DBCMS.get_cms_category_id(categoryName)
+ DBCMS.add_category_to_post(post_id, categoryId)
+ return post_id
+
+ @staticmethod
+ def get_last_added_post_id():
+ logger.debug("Get the id of the post inserted")
+ queryStr = "select MAX(id) FROM public.blog_blogpost;"
+ logger.debug("Query : " + queryStr)
+ result = DBCMS.select_query(queryStr)
+ return result
+
+ @staticmethod
+ def update_days(xdays, title):
+ logger.debug("Get the id of the post inserted")
+# queryStr = "select MAX(id) FROM public.blog_blogpost;"
+ queryStr = "UPDATE public.blog_blogpost SET created=current_timestamp - interval '%s day' WHERE title='%s';" % (
+ xdays, title)
+ logger.debug("Query : " + queryStr)
+ result = DBCMS.update_query(queryStr)
+ return result
+
+ @staticmethod
+ def add_category_to_post(postId, categoryId):
+ logger.debug("bind category into inserted post: " + postId)
+ queryStr = "INSERT INTO public.blog_blogpost_categories(blogpost_id, blogcategory_id) VALUES (%s, %s);" % (
+ postId, categoryId)
+ logger.debug("Query : " + queryStr)
+ DBCMS.insert_query(queryStr)
+
+ @staticmethod
+ def get_documentation_page_id():
+ logger.debug("Retrive id of documentation page: ")
+ queryStr = "SELECT id FROM public.pages_page WHERE title = 'Documentation' LIMIT 1;"
+ logger.debug("Query : " + queryStr)
+ result = DBCMS.select_query(queryStr)
+ return result
+
+ @staticmethod
+ def get_last_inserted_page_id():
+ logger.debug("Retrive id of last page inserted: ")
+ queryStr = "select MAX(id) FROM public.pages_page;"
+ logger.debug("Query : " + queryStr)
+ result = DBCMS.select_query(queryStr)
+ return result
+
+ @staticmethod
+ def delete_old_tips_of_the_day():
+ logger.debug("Delete all posts ")
+ queryStr = "DELETE FROM public.blog_blogpost_categories WHERE id>0;"
+ logger.debug("Query : " + queryStr)
+ DBCMS.insert_query(queryStr)
+ queryStr = "DELETE FROM public.blog_blogpost WHERE id>0;;"
+ logger.debug("Query : " + queryStr)
+ DBCMS.insert_query(queryStr)
+
+ @staticmethod
+ def insert_page(title, content, parent_id=None):
+ logger.debug("Retrive id of documentation page: ")
+ if parent_id is None:
+ parent_id = DBCMS.get_documentation_page_id()
+ queryStr = "INSERT INTO public.pages_page(" \
+ "keywords_string, title, slug, _meta_title, description, gen_description, created, updated, status, publish_date, expiry_date, short_url, in_sitemap, _order, in_menus, titles, content_model, login_required, parent_id, site_id)" \
+ "VALUES ('', '%s', '%s-slug', '', '%s', true, current_timestamp - interval '1 day', current_timestamp - interval '1 day', 2, current_timestamp - interval '1 day', NULL, '', true, 0, '1,2,3', '%s', 'richtextpage', true, %s, 1);" % (
+ title, title, content, title, parent_id)
+ logger.debug("Query : " + queryStr)
+ DBCMS.insert_query(queryStr)
+
+ createdPageId = DBCMS.get_last_inserted_page_id()
+ logger.debug(
+ "Bind the page with the rich text content related to this page")
+ queryStr = "INSERT INTO public.pages_richtextpage(page_ptr_id, content) VALUES (%s, '<p>%s</p>');" % (
+ createdPageId, content)
+ logger.debug("Query : " + queryStr)
+ DBCMS.insert_query(queryStr)
+ return createdPageId
+
+ @staticmethod
+ def create_faq():
+ title = "title_FAQ" + Helper.rand_string("randomString")
+ description = "description_FAQ_" + Helper.rand_string("randomString")
+ DBCMS.delete_old_tips_of_the_day()
+ postId = DBCMS.insert_cms_new_post(title, description, "FAQ")
+ assertTrue(len(postId) > 0 and not None)
+ return title, description
+
+ @staticmethod
+ def create_news():
+ title = "title_News" + Helper.rand_string("randomString")
+ description = "description_News" + Helper.rand_string("randomString")
+ postId = DBCMS.insert_cms_new_post(title, description, "News")
+ assertTrue(len(postId) > 0 and not None)
+ return title, description
+
+ @staticmethod
+ def create_announcement():
+ title = "title_Announcement_" + Helper.rand_string("randomString")
+ description = "description_Announcement_" + \
+ Helper.rand_string("randomString")
+ postId = DBCMS.insert_cms_new_post(title, description, "Announcement")
+ assertTrue(len(postId) > 0 and not None)
+ return title, description
+
+ @staticmethod
+ def create_page(parent_id=None):
+ title = "title_Of_Page_" + Helper.rand_string("randomString")
+ description = "description_Of_Page_" + \
+ Helper.rand_string("randomString")
+ createdPageId = DBCMS.insert_page(title, description)
+ assertTrue(len(createdPageId) > 0 and not None)
+ return title, description
+
+ @staticmethod
+ def update_X_days_back_post(title, xdays):
+ logger.debug("Get the id of the post inserted")
+ queryStr = "UPDATE blog_blogpost SET created = current_timestamp - interval '%s day', publish_date=current_timestamp - interval '%s day' WHERE title= '%s' ;" % (
+ xdays, xdays, title)
+ logger.debug("Query : " + queryStr)
+ DBCMS.update_query(queryStr)
+
+ @staticmethod
+ def create_announcements(x):
+ listOfTitleAnDescriptions = []
+ for _ in range(x):
+ # print x ->str
+ title = "title_Announcement_" + Helper.rand_string("randomString")
+ description = "description_Announcement_" + \
+ Helper.rand_string("randomString")
+ postId = DBCMS.insert_cms_new_post(
+ title, description, "Announcement")
+ assertTrue(len(postId) > 0 and not None)
+ xList = [title, description]
+ listOfTitleAnDescriptions.append(xList)
+ return listOfTitleAnDescriptions
diff --git a/services/database/db_general.py b/services/database/db_general.py
new file mode 100755
index 0000000..c850d3a
--- /dev/null
+++ b/services/database/db_general.py
@@ -0,0 +1,416 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from datetime import datetime
+import sqlite3
+
+from django.conf import settings
+from django.db import transaction
+import psycopg2
+
+from services.logging_service import LoggingServiceFactory
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class DBGeneral:
+
+ @staticmethod
+ # desigredDB: Use 'default' for CI General and 'em_db' for EM General
+ # (according to settings.DATABASES).
+ def return_db_native_connection(desigredDB):
+ dbConnectionStr = "dbname='" + str(settings.SINGLETONE_DB[desigredDB]['NAME']) + \
+ "' user='" + str(settings.SINGLETONE_DB[desigredDB]['USER']) + \
+ "' host='" + str(settings.SINGLETONE_DB[desigredDB]['HOST']) + \
+ "' password='" + str(settings.SINGLETONE_DB[desigredDB]['PASSWORD']) + \
+ "' port='" + \
+ str(settings.SINGLETONE_DB[desigredDB]['PORT']) + "'"
+ return dbConnectionStr
+
+ @staticmethod
+ def insert_results(testType, testFeature, testResult, testName, testDuration, notes=" "):
+ try:
+ if settings.DATABASE_TYPE == 'sqlite':
+ dbfile = str(settings.DATABASES['default']['TEST_NAME'])
+ dbConn = sqlite3.connect(dbfile)
+ cur = dbConn.cursor()
+ else:
+ # Connect to General 'default'.
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection("default"))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ except Exception as e:
+ errorMsg = "Failed to create connection to General." + str(e)
+ raise Exception(errorMsg)
+ try: # Create INSERT query.
+ if settings.DATABASE_TYPE == 'sqlite':
+ query_str = 'INSERT INTO ice_test_results (testType, testFeature, testResult, testName, notes,'\
+ 'create_time, build_id, duration) VALUES (?, ?, ?, ?, ?, ?, ?, ?);'
+ else:
+ query_str = 'INSERT INTO ice_test_results ("testType", "testFeature", "testResult", "testName", notes,'\
+ 'create_time, build_id, duration) VALUES (%s, %s, %s, %s, %s, %s, %s, %s);'
+ cur.execute(query_str, (testType, testFeature, testResult, testName, notes, str(datetime.now()),
+ settings.ICE_BUILD_REPORT_NUM, testDuration))
+ dbConn.commit()
+ logger.debug("Test result in DB - " + testResult)
+ except Exception as e:
+ logger.error(e)
+ errorMsg = "Failed to insert results to DB." + str(e)
+ raise Exception(errorMsg)
+ dbConn.close()
+
+ @staticmethod
+ def select_query(queryStr, return_type="str", fetch_num=1):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ logger.debug("Query: " + queryStr)
+ cur.execute(queryStr)
+ if return_type == "str":
+ if fetch_num == 1:
+ result = str(cur.fetchone())
+ else:
+ result = str(cur.fetchall())
+ if result != 'None':
+ # formatting strings e.g uuid
+ if(result.find("',)") != -1):
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ if return_type == "list":
+ if fetch_num == 1:
+ result = list(cur.fetchone())
+ else:
+ result = [item[0] for item in cur.fetchall()]
+ dbConn.close()
+ logger.debug("Query result: " + str(result))
+ return result
+ except:
+ raise Exception("Couldn't fetch answer using the given query.")
+
+ @staticmethod
+ def insert_query(queryStr):
+ try:
+ nativeIceDb = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = nativeIceDb
+ cur = dbConn.cursor()
+ logger.debug("Query: " + queryStr)
+ cur.execute(queryStr)
+ dbConn.commit()
+ dbConn.close()
+ logger.debug("Insert query success!")
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ logger.error(e)
+ transaction.rollback()
+ raise Exception("Couldn't fetch answer using the given query.")
+
+ @staticmethod
+ def update_query(queryStr):
+ try:
+ nativeIceDb = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = nativeIceDb
+ cur = dbConn.cursor()
+ logger.debug("Query: " + queryStr)
+ cur.execute(queryStr)
+ dbConn.commit()
+ dbConn.close()
+ logger.debug("Update query success!")
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ logger.error(e)
+ transaction.rollback()
+ raise Exception("Couldn't fetch answer using the given query.")
+
+ @staticmethod
+ def select_where_email(queryColumnName, queryTableName, email):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "select %s from %s WHERE Email = '%s';" % (
+ queryColumnName, queryTableName, email)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ result = str(cur.fetchone())
+ if(result.find("',)") != -1): # formatting strings e.g uuid
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ dbConn.close()
+ logger.debug("Query result: " + str(result))
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_where_email FAILED "
+ raise Exception(errorMsg, "select_where_email")
+ raise
+
+ @staticmethod
+ def select_from(queryColumnName, queryTableName, fetchNum):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ cur = dbConn.cursor()
+ queryStr = "select %s from %s;" % (queryColumnName, queryTableName)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ if (fetchNum == 0):
+ result = str(cur.fetchall())
+ elif (fetchNum == 1):
+ result = str(cur.fetchone())
+ if(result.find("',)") != -1): # formatting strings e.g uuid
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ dbConn.close()
+ logger.debug("Query result: " + str(result))
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "select_from FAILED " + str(e)
+ raise Exception(errorMsg, "select_from")
+
+ @staticmethod
+ def select_where(queryColumnName, queryTableName, whereParametrType, whereParametrValue, fetchNum):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ cur = dbConn.cursor()
+ queryStr = "select %s from %s Where %s = '%s';" % (
+ queryColumnName, queryTableName, whereParametrType, whereParametrValue)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ if (fetchNum == 0):
+ result = list(cur.fetchall())
+ elif (fetchNum == 1):
+ result = str(cur.fetchone())
+ if(result.find("',)") != -1): # formatting strings e.g uuid
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ dbConn.close()
+ logger.debug("Query result: " + str(result))
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_where FAILED "
+ raise Exception(errorMsg, "select_where")
+
+ @staticmethod
+ def select_where_order_by_desc(queryColumnName, queryTableName, whereParametrType, whereParametrValue, order_by):
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ cur = dbConn.cursor()
+ queryStr = "select %s from %s Where %s = '%s' order by %s desc limit 1;" \
+ % (queryColumnName, queryTableName, whereParametrType, whereParametrValue, order_by)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ result = str(cur.fetchall())
+ result = DBGeneral.list_format(result)
+ dbConn.close()
+ return result
+
+ @staticmethod
+ def select_where_dict(queryColumnName, queryTableName, whereParametrType):
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ cur = dbConn.cursor()
+ x = ""
+ count = 0
+ for key, val in whereParametrType.items():
+ x += "%s='%s'" % (key, val)
+ if len(whereParametrType.items()) - count > 1:
+ x += ' and '
+ count += 1
+ queryStr = "select %s from %s Where %s;" \
+ % (queryColumnName, queryTableName, x)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ result = str(cur.fetchall())
+ result = DBGeneral.list_format(result)
+ dbConn.close()
+ return result
+
+ @staticmethod
+ def select_where_not_and_order_by_desc(queryColumnName, queryTableName, whereParametrType,
+ whereParametrValue, parametrTypeAnd, parametrAnd, order_by):
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ cur = dbConn.cursor()
+ queryStr = "select %s from %s Where %s = '%s' and %s != '%s' order by %s desc limit 1;" \
+ % (queryColumnName, queryTableName, whereParametrType, whereParametrValue,
+ parametrTypeAnd, parametrAnd, order_by)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ result = str(cur.fetchall())
+ result = DBGeneral.list_format(result)
+ dbConn.close()
+ return result
+
+ @staticmethod
+ def select_where_and(queryColumnName, queryTableName, whereParametrType, whereParametrValue,
+ parametrTypeAnd, parametrAnd, fetchNum):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "select %s from %s Where %s = '%s' and %s = '%s';" % (
+ queryColumnName, queryTableName, whereParametrType, whereParametrValue, parametrTypeAnd, parametrAnd)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ if (fetchNum == 0):
+ result = str(cur.fetchall())
+ result = DBGeneral.list_format(result)
+ elif (fetchNum == 1):
+ result = str(cur.fetchone())
+ if(result.find("',)") != -1): # formatting strings e.g uuid
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ dbConn.close()
+ logger.debug("Query result: " + str(result))
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_where_and FAILED "
+ raise Exception(errorMsg, "select_where_and")
+
+ @staticmethod
+ def select_where_is_bigger(queryColumnName, queryTableName, whereParametrType, whereParametrValue, parametrTypeAnd, parametrAnd, fetchNum):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "select %s from %s Where %s = '%s' and %s > %s;" % (
+ queryColumnName, queryTableName, whereParametrType, whereParametrValue, parametrTypeAnd, parametrAnd)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ if (fetchNum == 0):
+ result = cur.fetchall()
+ elif (fetchNum == 1):
+ result = cur.fetchone()
+ if(result.find("',)") != -1): # formatting strings e.g uuid
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ dbConn.close()
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_where_is_bigger FAILED "
+ raise Exception(errorMsg, "select_where_is_bigger")
+
+ @staticmethod
+ def update_where(queryTableName, setParametrType, setparametrValue, whereParametrType, whereParametrValue):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "UPDATE %s SET %s = '%s' Where %s = '%s';" % (
+ queryTableName, setParametrType, setparametrValue, whereParametrType, whereParametrValue)
+ cur.execute(queryStr)
+ dbConn.commit()
+ logger.debug("Query : " + queryStr)
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Could not Update User"
+ logger.debug(e)
+ raise Exception(errorMsg, "Update")
+ finally:
+ dbConn.close()
+
+ @staticmethod
+ def update_by_query(queryStr):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ dbConn.commit()
+ dbConn.close()
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "Could not Update User"
+ raise Exception(errorMsg, "Update")
+
+ @staticmethod
+ def update_where_and(queryTableName, setParametrType, parametrValue, changeToValue, whereParametrType, setParametrType2, setParametrValue2, whereParametrType2, whereParametrValue2):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "UPDATE %s SET %s = '%s', %s = '%s' Where %s = '%s' and %s = '%s';" % (
+ queryTableName, setParametrType, changeToValue, setParametrType2, setParametrValue2, whereParametrType, parametrValue, whereParametrType2, whereParametrValue2)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ dbConn.commit()
+ dbConn.close()
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "Could not Update User"
+ raise Exception(errorMsg, "Update")
+
+ @staticmethod
+ def list_format(un_listed):
+ un_listed = un_listed[1:-1]
+ un_listed = un_listed.replace("',), ('", "|||")
+ un_listed = un_listed.replace("(u'", "") # Format list
+ un_listed = un_listed[1:-1].replace("('", "") # Format list
+ un_listed = un_listed.replace("',)", "") # Format list
+ listed = un_listed[1:-2].split("|||")
+ return listed
+
+ @staticmethod
+ def get_vendors_list():
+ # Select approved vendors from db.
+ vendors_list = DBGeneral.select_where(
+ "name", "ice_vendor", "public", "TRUE", 0)
+ return vendors_list
diff --git a/services/database/db_user.py b/services/database/db_user.py
new file mode 100644
index 0000000..d347dd2
--- /dev/null
+++ b/services/database/db_user.py
@@ -0,0 +1,417 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import time
+
+from django.conf import settings
+import psycopg2
+
+from services.constants import Constants
+from services.database.db_bridge import DBBridge
+from services.database.db_general import DBGeneral
+from services.database.db_virtual_function import DBVirtualFunction
+from services.frontend.base_actions.wait import Wait
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class DBUser:
+
+ @staticmethod
+ def get_activation_url(email):
+ # Fetch one user ID.
+ uuid = DBUser.select_user_uuid(email)
+ # Fetch one user ID.
+ index = DBGeneral.select_where_email("id", "auth_user", email)
+ activation_token = DBGeneral.select_where(
+ "activation_token", "ice_custom_user", "user_ptr_id", index, 1)
+ # / activate /:userID /:token
+ activationUrl = settings.ICE_PORTAL_URL + '/#/activate/' + \
+ str(uuid) + '/' + str(activation_token)
+ logger.debug("activationUrl :" + activationUrl)
+ return activationUrl
+
+ @staticmethod
+ def get_contact_signup_url(invite_token, uuid, email, fullName, phoneNum, companyName):
+ companyId = DBGeneral.select_where(
+ "uuid", "ice_vendor", "name", companyName, 1)
+ signUpURLforContact = settings.ICE_PORTAL_URL + "#/signUp?invitation=" + invite_token + \
+ "&email=" + email + "&full_name=" + fullName + \
+ "&phone_number=" + phoneNum + "&company=" + companyId
+ logger.debug("SignUpURLforContact :" + signUpURLforContact)
+ return signUpURLforContact
+
+ @staticmethod
+ def select_invitation_token(queryColumnName, queryTableName, whereParametrType, whereParametrValue, email, fetchNum):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "select %s from %s Where %s = '%s' and email = '%s' ;" % (
+ queryColumnName, queryTableName, whereParametrType, whereParametrValue, email)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ if (fetchNum == 0):
+ result = str(cur.fetchall())
+ elif (fetchNum == 1):
+ result = str(cur.fetchone())
+ if(result.find("',)") != -1): # formatting strings e.g uuid
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ dbConn.close()
+ if result == None:
+ errorMsg = "select_where_pr_state FAILED "
+ logger.error(errorMsg)
+ raise
+ logger.debug("Query result: " + str(result))
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_where FAILED "
+ raise Exception(errorMsg, "select_where")
+
+ @staticmethod
+ def get_el_name(vfName):
+ try:
+ # Fetch one AT&T user ID.
+ engagement_id = DBVirtualFunction.select_eng_uuid(vfName)
+ engagement_manual_id = DBGeneral.select_where(
+ "engagement_manual_id", "ice_engagement", "uuid", engagement_id, 1)
+ reviewer_id = DBGeneral.select_where(
+ "reviewer_id", "ice_engagement", "engagement_manual_id", engagement_manual_id, 1)
+ engLeadFullName = DBGeneral.select_where_and(
+ "full_name", "ice_user_profile", "id", reviewer_id, "role_id", "2", 1)
+ return engLeadFullName
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "get_el_name FAILED "
+ raise Exception(errorMsg, "get_el_name")
+
+ @staticmethod
+ def get_email_by_full_name(fullname):
+ # try:
+ query_str = "select email from ice_user_profile where full_name = '%s';" % (
+ fullname)
+ user_email = DBGeneral.select_query(query_str)
+ return user_email
+# except: # If failed - count the failure and add the error to list of errors.
+# errorMsg = "get_email_by_full_name FAILED "
+# raise Exception(errorMsg, "get_el_name")
+
+ @staticmethod
+ def select_recent_vf_of_user(user_uuid, fetchNum):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "SELECT vf_id FROM public.ice_recent_engagement where user_uuid = '%s' order by last_update desc limit 20;" % (
+ user_uuid)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ if (fetchNum == 0):
+ result = str(cur.fetchall())
+ elif (fetchNum == 1):
+ result = str(cur.fetchone())
+ if(result.find("',)") != -1): # formatting strings e.g uuid
+ result = result.partition('\'')[-1].rpartition('\'')[0]
+ elif(result.find(",)") != -1): # formatting ints e.g id
+ result = result.partition('(')[-1].rpartition(',')[0]
+ dbConn.close()
+ logger.debug("Query result: " + str(result))
+ return result
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_where FAILED "
+ raise Exception(errorMsg, "select_where")
+
+ @staticmethod
+ def select_el_email(vfName):
+ try:
+ # Fetch one AT&T user ID.
+ engagement_id = DBVirtualFunction.select_eng_uuid(vfName)
+ engagement_manual_id = DBGeneral.select_where(
+ "engagement_manual_id", "ice_engagement", "uuid", engagement_id, 1)
+ reviewer_id = DBGeneral.select_where(
+ "reviewer_id", "ice_engagement", "engagement_manual_id", engagement_manual_id, 1)
+ engLeadEmail = DBGeneral.select_where_and(
+ "email", "ice_user_profile", "id", reviewer_id, "role_id", "2", 1)
+ return engLeadEmail
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_el_email FAILED "
+ raise Exception(errorMsg, "select_el_email")
+
+ @staticmethod
+ def select_user_native_id(email):
+ try:
+ # Fetch one AT&T user ID.
+ engLeadId = DBUser.select_user_profile_property(email, "id")
+ return engLeadId
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_user_native_id FAILED "
+ raise Exception(errorMsg, "select_user_native_id")
+
+ @staticmethod
+ def select_personal_next_step(email):
+ user_id = DBUser.select_user_native_id(email)
+ return DBGeneral.select_where("uuid", "ice_next_step", "owner_id", user_id, 1)
+
+ @staticmethod
+ def select_pr_email(vfName):
+ try:
+ # Fetch one AT&T user ID.
+ engagement_id = DBVirtualFunction.select_eng_uuid(vfName)
+ engagement_manual_id = DBGeneral.select_where(
+ "engagement_manual_id", "ice_engagement", "uuid", engagement_id, 1)
+ reviewer_id = DBGeneral.select_where(
+ "peer_reviewer_id", "ice_engagement", "engagement_manual_id", engagement_manual_id, 1)
+ engLeadEmail = DBGeneral.select_where(
+ "email", "ice_user_profile", "id", reviewer_id, 1)
+ return engLeadEmail
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_el_email FAILED "
+ raise Exception(errorMsg, "select_el_email")
+
+ @staticmethod
+ def get_notification_id_by_email(userEmail):
+ uuid = DBGeneral.select_where_email(
+ "id", "ice_user_profile", userEmail)
+ notifIDs = DBGeneral.select_where(
+ "uuid", "ice_notification", "user_id", uuid, 0)
+ return notifIDs
+
+ @staticmethod
+ def get_not_seen_notifications_number_by_email(user_email, is_negative=False):
+ user_id = DBGeneral.select_where_email(
+ "id", Constants.DBConstants.IceTables.USER_PROFILE, user_email)
+ notifications_number = DBGeneral.select_where_and(
+ Constants.DBConstants.Queries.COUNT, Constants.DBConstants.IceTables.NOTIFICATION, "user_id", user_id, "is_read", "False", 1)
+ if is_negative:
+ counter = 0
+ while notifications_number != "0" and counter <= Constants.Dashboard.Avatar.Notifications.Count.RETRIES_NUMBER:
+ notifications_number = DBGeneral.select_where_and(
+ Constants.DBConstants.Queries.COUNT, Constants.DBConstants.IceTables.NOTIFICATION, "user_id", user_id, "is_read", "False", 1)
+ time.sleep(1)
+ counter += 1
+ return notifications_number
+
+ @staticmethod
+ def get_eng_lead_email_per_enguuid(enguuid):
+ reviewer_id = DBGeneral.select_where(
+ "reviewer_id", Constants.DBConstants.IceTables.ENGAGEMENT, "uuid", enguuid, 1)
+ engLeadEmail = DBGeneral.select_where(
+ "email", Constants.DBConstants.IceTables.USER_PROFILE, "id", reviewer_id, 1)
+ return engLeadEmail
+
+ @staticmethod
+ def select_all_user_engagements(engLeadID):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "select COUNT(*) from ice_engagement_engagement_team Where iceuserprofile_id = %s and (select engagement_stage from public.ice_engagement where uuid = engagement_id LIMIT 1) != 'Archived';" % (
+ engLeadID)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ result = cur.fetchall()
+ dbConn.close()
+ logger.debug("Query result: " + str(result))
+ logger.debug(result[0][0])
+ return result[0][0]
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_user_engagements_by_stage FAILED "
+ raise Exception(errorMsg, "select_user_engagements_by_stage")
+
+ @staticmethod
+ def select_user_engagements_by_stage(stage, engLeadID):
+ try:
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection('em_db'))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ queryStr = "select count(*) from ice_engagement INNER JOIN ice_engagement_engagement_team ON ice_engagement_engagement_team.engagement_id= ice_engagement.uuid Where (ice_engagement.engagement_stage = '%s') and (ice_engagement_engagement_team.iceuserprofile_id = %s );" % (
+ stage, engLeadID)
+ logger.debug("Query : " + queryStr)
+ cur.execute(queryStr)
+ result = cur.fetchall()
+ dbConn.close()
+ logger.debug("Query result: " + str(result))
+ logger.debug(result[0][0])
+ return result[0][0]
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "select_user_engagements_by_stage FAILED "
+ raise Exception(errorMsg, "select_user_engagements_by_stage")
+
+ @staticmethod
+ def set_new_temp_password(email):
+ encodePass = DBGeneral.select_where_email(
+ "password", "auth_user", Constants.Users.Admin.EMAIL)
+ # Fetch one user ID.
+ index = DBGeneral.select_where_email("id", "auth_user", email)
+ DBGeneral.update_where(
+ "ice_custom_user", "temp_password", encodePass, "user_ptr_id", index)
+
+ @staticmethod
+ def set_password_to_default(email):
+ encodePass = DBGeneral.select_where_email(
+ "password", "auth_user", Constants.Users.Admin.EMAIL)
+ DBGeneral.update_where(
+ "auth_user", "password", encodePass, "email", email)
+
+ @staticmethod
+ def select_el_not_in_engagement(el_name, pr_name):
+ query_str = "select full_name from ice_user_profile where role_id = 2 and full_name != '%s' and full_name != '%s';" % (
+ el_name, pr_name)
+ new_user = DBGeneral.select_query(query_str)
+ if new_user == 'None':
+ new_user = DBUser.update_to_el_not_in_engagement()
+ return new_user
+
+ @staticmethod
+ def select_user_uuid(email):
+ user_uuid = DBUser.select_user_profile_property(email, "uuid")
+ return user_uuid
+
+ @staticmethod
+ def select_access_key(email):
+ access_key = DBUser.select_user_profile_property(email, "rgwa_access_key")
+ return access_key
+
+ @staticmethod
+ def select_secret_key(email):
+ secret_key = DBUser.select_user_profile_property(email, "rgwa_secret_key")
+ return secret_key
+
+ @staticmethod
+ def update_to_el_not_in_engagement():
+ query_str = "select uuid from ice_user_profile where role_id = 1 ;"
+ user_uuid = DBGeneral.select_query(query_str)
+ updatequery = "UPDATE ice_user_profile SET role_id=2 ,full_name = 'el_for_test' WHERE uuid = '%s' ;" % (
+ user_uuid)
+ DBGeneral.update_query(updatequery)
+ updatequery = "UPDATE ice_user_profile SET role_id=2 WHERE full_name = '%s' ;" % (
+ 'el_for_test')
+ DBGeneral.update_query(updatequery)
+ return 'el_for_test'
+
+ @staticmethod
+ def rollback_for_el_not_in_engagement():
+ query_str = "select uuid from ice_user_profile where full_name = 'el_for_test';"
+ user_uuid = DBGeneral.select_query(query_str)
+ fullName = DBBridge.helper_rand_string("randomString")
+ updatequery = "UPDATE ice_user_profile SET role_id=1,full_name = '%s' WHERE uuid = '%s' ;" % (
+ fullName, user_uuid)
+ DBGeneral.update_query(updatequery)
+
+ @staticmethod
+ def set_engagement_peer_reviewer(engagement_uuid, email):
+ user_uuid = DBUser.select_user_uuid(email)
+ update_query = "UPDATE ice_user_profile SET role_id=2 WHERE uuid = '%s';" % user_uuid
+ DBGeneral.update_query(update_query)
+
+ user_id = DBGeneral.select_query(
+ "SELECT id FROM ice_user_profile WHERE uuid = '%s';" % user_uuid)
+ update_query = "UPDATE ice_engagement SET peer_reviewer_id=%s WHERE uuid = '%s';" % (
+ user_id, engagement_uuid)
+ DBGeneral.update_query(update_query)
+
+ @staticmethod
+ def select_user_profile_property(user_email, property_name):
+ return DBGeneral.select_where(property_name, "ice_user_profile", "email", user_email, 1)
+
+ @staticmethod
+ def validate_user_profile_settings_in_db(user_email, checked):
+ Wait.page_has_loaded()
+ regular_email_updates = DBUser.select_user_profile_property(
+ user_email, 'regular_email_updates')
+ DBBridge.helper_internal_assert(regular_email_updates, checked)
+ email_updates_on_every_notification = \
+ DBUser.select_user_profile_property(
+ user_email, 'email_updates_on_every_notification')
+ DBBridge.helper_internal_assert(
+ email_updates_on_every_notification, checked)
+ email_updates_daily_digest = DBUser.select_user_profile_property(
+ user_email, 'email_updates_daily_digest')
+ DBBridge.helper_internal_assert(
+ email_updates_daily_digest, not checked)
+
+ @staticmethod
+ def retrieve_admin_ssh_from_db():
+ ssh_key = DBGeneral.select_where(
+ 'ssh_public_key', Constants.DBConstants.IceTables.USER_PROFILE,
+ 'email', Constants.Users.Admin.EMAIL, 1)
+ return ssh_key
+
+ @staticmethod
+ def get_access_key(user_uuid):
+ counter = 0
+ access_key = DBGeneral.select_where(
+ "rgwa_access_key", Constants.DBConstants.IceTables.USER_PROFILE, "uuid", user_uuid, 1)
+ while access_key == "None" and counter <= Constants.RGWAConstants.RETRIES_NUMBER:
+ time.sleep(session.wait_until_time_pause)
+ logger.debug(
+ "rgwa_access_key are not ready yet, trying again (%s of 20)" % counter)
+ access_key = DBGeneral.select_where(
+ "rgwa_access_key", Constants.DBConstants.IceTables.USER_PROFILE, "uuid", user_uuid, 1)
+ counter += 1
+ return access_key
+
+ @staticmethod
+ def get_access_secret(user_uuid):
+ counter = 0
+ access_secret = DBGeneral.select_where(
+ "rgwa_secret_key", Constants.DBConstants.IceTables.USER_PROFILE, "uuid", user_uuid, 1)
+ while access_secret == "None" and counter <= Constants.RGWAConstants.RETRIES_NUMBER:
+ time.sleep(session.wait_until_time_pause)
+ logger.debug(
+ "rgwa_secret_key are not ready yet, trying again (%s of 100)" % counter)
+ access_secret = DBGeneral.select_where(
+ "rgwa_secret_key", Constants.DBConstants.IceTables.USER_PROFILE, "uuid", user_uuid, 1)
+
+ counter += 1
+ return access_secret
diff --git a/services/database/db_virtual_function.py b/services/database/db_virtual_function.py
new file mode 100644
index 0000000..143bca2
--- /dev/null
+++ b/services/database/db_virtual_function.py
@@ -0,0 +1,227 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import uuid
+
+from django.conf import settings
+import psycopg2
+
+from services.constants import Constants
+from services.database.db_bridge import DBBridge
+from services.database.db_general import DBGeneral
+from services.logging_service import LoggingServiceFactory
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class DBVirtualFunction:
+
+ @staticmethod
+ def insert_ecomp_release(uuid, name, ui_visibility="TRUE"):
+ try:
+ queryTableName = "ice_ecomp_release"
+ # Connect to General 'default'.
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection("em_db"))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ logger.debug("DATABASE_TYPE: " + settings.DATABASE_TYPE)
+ except Exception as e:
+ errorMsg = "Failed to create connection to General: " + str(e)
+ raise Exception(errorMsg)
+ try:
+ logger.debug("DATABASE_TYPE: " + settings.DATABASE_TYPE)
+ # Create INSERT query.
+ queryStr = "INSERT INTO %s (""uuid, name, weight, ui_visibility"") VALUES ('%s', '%s', '%s', '%s');" % (
+ queryTableName, uuid, name, 0, ui_visibility)
+ logger.debug("Query: " + queryStr)
+ cur.execute(queryStr) # Execute query.
+ dbConn.commit()
+ logger.debug("Test results are in General now.")
+ except Exception as e:
+ errorMsg = "Failed to insert ECOMP release to General:" + str(e)
+ raise Exception(errorMsg)
+ dbConn.close()
+
+ @staticmethod
+ def delete_ecomp_release(uuid, name):
+ try:
+ queryTableName = "ice_ecomp_release"
+ # Connect to General 'default'.
+ dbConn = psycopg2.connect(
+ DBGeneral.return_db_native_connection("em_db"))
+ dbConn = dbConn
+ cur = dbConn.cursor()
+ except Exception as e:
+ errorMsg = "Failed to create connection to DBGeneral.because :" + \
+ str(e)
+ raise Exception(errorMsg)
+ try:
+ # Create INSERT query.
+ queryStr = "DELETE FROM %s WHERE uuid = '%s';" % (
+ queryTableName, uuid)
+ logger.debug("Query: " + queryStr)
+ cur.execute(queryStr) # Execute query.
+ dbConn.commit()
+ logger.debug("Test results are in General now.")
+ except Exception as e:
+ errorMsg = "Failed to delete ECOMP release from General . because :" + \
+ str(e)
+ raise Exception(errorMsg)
+ raise
+ dbConn.close()
+
+ @staticmethod
+ def select_next_steps_ids(engagement_uuid):
+ ice_next_steps = DBGeneral.select_where(
+ "uuid", "ice_next_step", "engagement_id", engagement_uuid, 0)
+ return ice_next_steps
+
+ @staticmethod
+ def select_next_steps_uuids_by_stage(engagement_uuid, engagement_stage):
+ query = "SELECT uuid FROM %s WHERE engagement_id='%s' AND engagement_stage='%s' ORDER BY position;" % (
+ Constants.DBConstants.IceTables.NEXT_STEP, engagement_uuid, engagement_stage)
+ return DBGeneral.select_query(query, "list", 0)
+
+ @staticmethod
+ def update_next_step_position(next_step_uuid, new_index):
+ DBGeneral.update_where(
+ "ice_next_step", "position", new_index, "uuid", next_step_uuid)
+
+ @staticmethod
+ def select_next_step_description(next_step_uuid):
+ return DBGeneral.select_where("description", "ice_next_step", "uuid", next_step_uuid, 1)
+
+ @staticmethod
+ def select_eng_uuid(vf_name):
+ return DBGeneral.select_where("engagement_id", "ice_vf", "name", vf_name, 1)
+
+ @staticmethod
+ def select_engagment_uuid_by_vf_name(vfName):
+ engagement_id = DBGeneral.select_where(
+ "engagement_id", "ice_vf", "name", vfName, 1)
+ engagement_manual_id = DBGeneral.select_where(
+ "engagement_manual_id", "ice_engagement", "uuid", engagement_id, 1)
+ enguuid = DBGeneral.select_where(
+ "uuid", "ice_engagement", "engagement_manual_id", engagement_manual_id, 1)
+ return enguuid
+
+ @staticmethod
+ def select_vf_version_by_vf_name(vfName):
+ queryStr = "SELECT version FROM ice_vf WHERE name= '%s';" % vfName
+ version_name = str(DBGeneral.select_query(queryStr))
+ return version_name
+
+ @staticmethod
+ def select_vf_name_by_vf_version(version_name):
+ queryofname = "SELECT name FROM ice_vf WHERE version= '%s';" % version_name
+ vfNameDb = str(DBGeneral.select_query(queryofname))
+ return vfNameDb
+
+ @staticmethod
+ def return_expected_steps(engagement_uuid, stage, user_email):
+ steps_uuids = DBVirtualFunction.select_next_steps_uuids_by_stage(
+ engagement_uuid, stage)
+ personal_step_uuid = DBBridge.select_personal_next_step(user_email)
+ DBVirtualFunction.update_next_step_position(personal_step_uuid, 1)
+ steps_uuids.insert(0, personal_step_uuid)
+ return steps_uuids
+
+ @staticmethod
+ def get_engagement():
+ """Use this function instead of creating a new engagement where no need to"""
+ queryStr = "SELECT DISTINCT ice_engagement.uuid, engagement_manual_id, ice_vf.name, ice_user_profile.full_name, \
+ ice_user_profile.email, reviewer_table.full_name, reviewer_table.email, \
+ ice_deployment_target.version, ice_ecomp_release.name \
+ FROM ice_engagement LEFT JOIN ice_vf ON engagement_id = ice_engagement.uuid \
+ LEFT JOIN ice_user_profile reviewer_table ON reviewer_table.id = ice_engagement.reviewer_id \
+ LEFT JOIN ice_user_profile ON ice_user_profile.id = ice_engagement.peer_reviewer_id \
+ LEFT JOIN ice_deployment_target ON ice_deployment_target.uuid = ice_vf.deployment_target_id \
+ LEFT JOIN ice_ecomp_release ON ice_ecomp_release.uuid = ice_vf.ecomp_release_id \
+ WHERE ice_user_profile.id IS NOT NULL LIMIT 1;"
+ list_of_values = DBGeneral.select_query(queryStr, return_type="list")
+ list_of_keys = ["engagement_uuid", "engagement_manual_id", "vfName", "pr_name",
+ "pr_email", "el_name", "el_email", "target_aic", "ecomp_release"]
+ return dict(zip(list_of_keys, list_of_values))
+
+ @staticmethod
+ def insert_aic_version(ui_visibility="TRUE"):
+ new_aic_version = {
+ "uuid": str(uuid.uuid4()), "name": "AIC", "version": DBBridge.helper_rand_string("randomNumber", 2), "ui_visibility": ui_visibility, "weight": 0}
+ queryStr = "INSERT INTO public.ice_deployment_target( \
+ uuid, name, version, ui_visibility, weight) \
+ VALUES ('%s', '%s', '%s', '%s', %s);" % (new_aic_version['uuid'], new_aic_version['name'], new_aic_version['version'], new_aic_version['ui_visibility'], new_aic_version['weight'])
+ DBGeneral.insert_query(queryStr)
+ return new_aic_version
+
+ @staticmethod
+ def delete_aic_version(aic_uuid):
+ DBGeneral.insert_query(
+ "DELETE FROM public.ice_deployment_target WHERE uuid='%s';" % aic_uuid)
+
+ @staticmethod
+ def change_aic_version_weight(new_weight, old_weight):
+ DBGeneral.insert_query(
+ "UPDATE public.ice_deployment_target SET weight=%s WHERE weight=%s" % (new_weight, old_weight))
+
+ @staticmethod
+ def change_ecomp_release_weight(new_weight, old_weight):
+ DBGeneral.insert_query(
+ "UPDATE public.ice_ecomp_release SET weight=%s WHERE weight=%s" % (new_weight, old_weight))
+
+ @staticmethod
+ def select_aic_version_uuid(aic_version):
+ return DBGeneral.select_where("uuid", "ice_deployment_target", "version", aic_version, 1)
+
+ @staticmethod
+ def select_ecomp_release_uuid(ecomp_release):
+ return DBGeneral.select_where("uuid", "ice_ecomp_release", "name", ecomp_release, 1)
+
+ @staticmethod
+ def add_admin_to_eng_team(eng_uuid):
+ admin_db_id = DBGeneral.select_where(
+ 'id', Constants.DBConstants.IceTables.USER_PROFILE, 'email', Constants.Users.Admin.EMAIL, 1)
+ queryStr = "INSERT INTO public.ice_engagement_engagement_team(engagement_id, iceuserprofile_id) VALUES ('%s', '%s');" % (
+ eng_uuid, admin_db_id)
+ logger.debug("add_admin_to_eng_team Query: %s" % queryStr)
+ DBGeneral.insert_query(queryStr)
+
+ @staticmethod
+ def remove_engagement_from_recent(vf_uuid):
+ DBGeneral.insert_query(
+ "DELETE FROM %s WHERE vf_id='%s'" % (Constants.DBConstants.IceTables.RECENT, vf_uuid))
diff --git a/services/frontend/__init__.py b/services/frontend/__init__.py
new file mode 100644
index 0000000..30d7152
--- /dev/null
+++ b/services/frontend/__init__.py
@@ -0,0 +1,38 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
diff --git a/services/frontend/__pycache__/__init__.cpython-36.pyc b/services/frontend/__pycache__/__init__.cpython-36.pyc
new file mode 100644
index 0000000..bd6d49d
--- /dev/null
+++ b/services/frontend/__pycache__/__init__.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/__pycache__/fe_checklist.cpython-36.pyc b/services/frontend/__pycache__/fe_checklist.cpython-36.pyc
new file mode 100644
index 0000000..d743311
--- /dev/null
+++ b/services/frontend/__pycache__/fe_checklist.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/__pycache__/fe_checklist_template.cpython-36.pyc b/services/frontend/__pycache__/fe_checklist_template.cpython-36.pyc
new file mode 100644
index 0000000..c781628
--- /dev/null
+++ b/services/frontend/__pycache__/fe_checklist_template.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/__pycache__/fe_cms.cpython-36.pyc b/services/frontend/__pycache__/fe_cms.cpython-36.pyc
new file mode 100644
index 0000000..b1c3fbe
--- /dev/null
+++ b/services/frontend/__pycache__/fe_cms.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/__pycache__/fe_dashboard.cpython-36.pyc b/services/frontend/__pycache__/fe_dashboard.cpython-36.pyc
new file mode 100644
index 0000000..5222e8e
--- /dev/null
+++ b/services/frontend/__pycache__/fe_dashboard.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/__pycache__/fe_detailed_view.cpython-36.pyc b/services/frontend/__pycache__/fe_detailed_view.cpython-36.pyc
new file mode 100644
index 0000000..6247ca3
--- /dev/null
+++ b/services/frontend/__pycache__/fe_detailed_view.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/__pycache__/fe_general.cpython-36.pyc b/services/frontend/__pycache__/fe_general.cpython-36.pyc
new file mode 100644
index 0000000..9b19b20
--- /dev/null
+++ b/services/frontend/__pycache__/fe_general.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/__pycache__/fe_invite.cpython-36.pyc b/services/frontend/__pycache__/fe_invite.cpython-36.pyc
new file mode 100644
index 0000000..2a94d33
--- /dev/null
+++ b/services/frontend/__pycache__/fe_invite.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/__pycache__/fe_overview.cpython-36.pyc b/services/frontend/__pycache__/fe_overview.cpython-36.pyc
new file mode 100644
index 0000000..eee24cc
--- /dev/null
+++ b/services/frontend/__pycache__/fe_overview.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/__pycache__/fe_user.cpython-36.pyc b/services/frontend/__pycache__/fe_user.cpython-36.pyc
new file mode 100644
index 0000000..54cb26d
--- /dev/null
+++ b/services/frontend/__pycache__/fe_user.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/__pycache__/fe_wizard.cpython-36-PYTEST.pyc b/services/frontend/__pycache__/fe_wizard.cpython-36-PYTEST.pyc
new file mode 100755
index 0000000..630c015
--- /dev/null
+++ b/services/frontend/__pycache__/fe_wizard.cpython-36-PYTEST.pyc
Binary files differ
diff --git a/services/frontend/__pycache__/fe_wizard.cpython-36.pyc b/services/frontend/__pycache__/fe_wizard.cpython-36.pyc
new file mode 100644
index 0000000..ca7c26f
--- /dev/null
+++ b/services/frontend/__pycache__/fe_wizard.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/base_actions/__init__.py b/services/frontend/base_actions/__init__.py
new file mode 100644
index 0000000..30d7152
--- /dev/null
+++ b/services/frontend/base_actions/__init__.py
@@ -0,0 +1,38 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
diff --git a/services/frontend/base_actions/__pycache__/__init__.cpython-36.pyc b/services/frontend/base_actions/__pycache__/__init__.cpython-36.pyc
new file mode 100644
index 0000000..567e40e
--- /dev/null
+++ b/services/frontend/base_actions/__pycache__/__init__.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/base_actions/__pycache__/click.cpython-36.pyc b/services/frontend/base_actions/__pycache__/click.cpython-36.pyc
new file mode 100644
index 0000000..7848aff
--- /dev/null
+++ b/services/frontend/base_actions/__pycache__/click.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/base_actions/__pycache__/enter.cpython-36.pyc b/services/frontend/base_actions/__pycache__/enter.cpython-36.pyc
new file mode 100644
index 0000000..df5e175
--- /dev/null
+++ b/services/frontend/base_actions/__pycache__/enter.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/base_actions/__pycache__/get.cpython-36.pyc b/services/frontend/base_actions/__pycache__/get.cpython-36.pyc
new file mode 100644
index 0000000..a95dc14
--- /dev/null
+++ b/services/frontend/base_actions/__pycache__/get.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/base_actions/__pycache__/wait.cpython-36.pyc b/services/frontend/base_actions/__pycache__/wait.cpython-36.pyc
new file mode 100644
index 0000000..29b73ba
--- /dev/null
+++ b/services/frontend/base_actions/__pycache__/wait.cpython-36.pyc
Binary files differ
diff --git a/services/frontend/base_actions/click.py b/services/frontend/base_actions/click.py
new file mode 100644
index 0000000..00470b7
--- /dev/null
+++ b/services/frontend/base_actions/click.py
@@ -0,0 +1,108 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from selenium.webdriver.common.action_chains import ActionChains
+
+from services.frontend.base_actions.wait import Wait
+from services.session import session
+
+
+class Click:
+
+ @staticmethod
+ def id(element_id, wait_for_page=False):
+ try:
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.id(element_id)
+ session.ice_driver.find_element_by_id(element_id).click()
+ except Exception as e: # If failed - count the failure and add the error to list of errors.
+ errorMsg = "Failed to click_on on ID " + element_id
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def name(element_name, wait_for_page=False):
+ try:
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.name(element_name)
+ session.ice_driver.find_element_by_name(element_name).click()
+ except Exception as e: # If failed - count the failure and add the error to list of errors.
+ errorMsg = "Failed to click_on on ID " + element_name
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def link_text(link_inner_text, wait_for_page=False):
+ try:
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.link_text(link_inner_text)
+ session.ice_driver.find_element_by_link_text(link_inner_text).click()
+ except Exception as e: # If failed - count the failure and add the error to list of errors.
+ errorMsg = "Failed to click_on on LINK TEXT " + link_inner_text
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def css(element_css, wait_for_page=False):
+ try:
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.css(element_css)
+ session.ice_driver.find_element_by_css_selector(element_css).click()
+ except Exception as e: # If failed - count the failure and add the error to list of errors.
+ errorMsg = "Failed to click_on on CSS Selector " + element_css
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def xpath(element_xpath, wait_for_page=False):
+ try:
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.xpath(element_xpath)
+ session.ice_driver.find_element_by_xpath(element_xpath).click()
+ except Exception as e: # If failed - count the failure and add the error to list of errors.
+ errorMsg = "Failed to click_on on XPATH " + element_xpath
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def drag_and_drop_by_css(source_css, xoffset, yoffset):
+ ns = session.ice_driver.find_element_by_id("step-description-1")
+ ActionChains(session.ice_driver).move_to_element(ns).perform()
+ Wait.css(source_css)
+ source_element = session.ice_driver.find_element_by_css_selector(source_css)
+ ActionChains(session.ice_driver).drag_and_drop_by_offset(source_element, xoffset, yoffset).perform()
diff --git a/services/frontend/base_actions/enter.py b/services/frontend/base_actions/enter.py
new file mode 100644
index 0000000..4577a3d
--- /dev/null
+++ b/services/frontend/base_actions/enter.py
@@ -0,0 +1,139 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from datetime import datetime
+import time
+
+from services.frontend.base_actions.wait import Wait
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+class Enter:
+
+ @staticmethod
+ def text_by_name(attr_name_value, typed_text, wait_for_page=False):
+ try: # Send keys to element in UI, by name locator (e.g. type something in text box).
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.name(attr_name_value)
+ session.ice_driver.find_element_by_name(attr_name_value).clear()
+ session.ice_driver.find_element_by_name(attr_name_value).send_keys(typed_text[:-1])
+ time.sleep(session.wait_until_time_pause)
+ session.ice_driver.find_element_by_name(attr_name_value).send_keys(typed_text[-1:])
+ except Exception as e: # If failed - count the failure and add the error to list of errors.
+ errorMsg = "Failed to type " + typed_text + " in text box"
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def text_by_xpath(attr_xpath_value, typed_text, wait_for_page=False):
+ try: # Send keys to element in UI, by name locator (e.g. type something in text box).
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.xpath(attr_xpath_value)
+ session.ice_driver.find_element_by_xpath(attr_xpath_value).clear()
+ session.ice_driver.find_element_by_xpath(attr_xpath_value).send_keys(typed_text[:-1])
+ time.sleep(session.wait_until_time_pause)
+ session.ice_driver.find_element_by_xpath(attr_xpath_value).send_keys(typed_text[-1:])
+ except Exception as e: # If failed - count the failure and add the error to list of errors.
+ errorMsg = "Failed to type " + typed_text + " in text box"
+ raise Exception(errorMsg, attr_xpath_value)
+
+ @staticmethod
+ def text_by_id(attr_id_value, typed_text, wait_for_page=False):
+ try: # Send keys to element in UI, by ID locator (e.g. type something in text box).
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.id(attr_id_value)
+ session.ice_driver.find_element_by_id(attr_id_value).clear()
+ session.ice_driver.find_element_by_id(attr_id_value).send_keys(typed_text[:-1])
+ time.sleep(session.wait_until_time_pause)
+ session.ice_driver.find_element_by_id(attr_id_value).send_keys(typed_text[-1:])
+ except Exception as e: # If failed - count the failure and add the error to list of errors.
+ errorMsg = "Failed to type " + typed_text + " in text box"
+ raise Exception(errorMsg, attr_id_value)
+
+ @staticmethod
+ def clear(attr_id_value):
+ try:
+ Wait.id(attr_id_value)
+ session.ice_driver.find_element_by_id(attr_id_value).clear()
+ except Exception as e:
+ errorMsg = "Failed to clear text box"
+ raise Exception(errorMsg, attr_id_value)
+
+ @staticmethod
+ def text_by_css(attr_css_value, typed_text, wait_for_page=False):
+ try: # Send keys to element in UI, by CSS locator (e.g. type something in text box).
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.css(attr_css_value)
+ session.ice_driver.find_element_by_css_selector(attr_css_value).clear()
+ session.ice_driver.find_element_by_css_selector(attr_css_value).send_keys(typed_text[:-1])
+ time.sleep(session.wait_until_time_pause)
+ session.ice_driver.find_element_by_css_selector(attr_css_value).send_keys(typed_text[-1:])
+ except Exception as e: # If failed - count the failure and add the error to list of errors.
+ errorMsg = "Failed to type " + typed_text + " in text box"
+ raise Exception(errorMsg, attr_css_value)
+
+ @staticmethod
+ def text_by_link_text(attr_link_text_value, typed_text, wait_for_page=False):
+ try: # Send keys to element in UI, by name locator (e.g. type something in text box).
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.link_text(attr_link_text_value)
+ session.ice_driver.find_element_by_link_text(attr_link_text_value).clear()
+ session.ice_driver.find_element_by_link_text(attr_link_text_value).send_keys(typed_text[:-1])
+ time.sleep(session.wait_until_time_pause)
+ session.ice_driver.find_element_by_link_text(attr_link_text_value).send_keys(typed_text[-1:])
+ except Exception as e: # If failed - count the failure and add the error to list of errors.
+ errorMsg = "Failed to type " + typed_text + " in text box"
+ raise Exception(errorMsg, attr_link_text_value)
+
+ @staticmethod
+ def date_picker(selector, property_name, wait_for_page=False):
+ try:
+ if wait_for_page:
+ Wait.page_has_loaded()
+ session.ice_driver.execute_script(
+ "var element = angular.element(document.querySelector('" + selector + "')); element.scope()." +
+ property_name + " = new Date('" + str(datetime.today().isoformat()) + "')")
+ except Exception as e:
+ errorMsg = "Failed to select date with datePicker."
+ raise Exception(errorMsg, str(e))
diff --git a/services/frontend/base_actions/get.py b/services/frontend/base_actions/get.py
new file mode 100644
index 0000000..8735c1b
--- /dev/null
+++ b/services/frontend/base_actions/get.py
@@ -0,0 +1,127 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from services.frontend.base_actions.wait import Wait
+from services.session import session
+
+
+class Get:
+
+ @staticmethod
+ def by_id(attr_id_value, wait_for_page=False):
+ try:
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.id(attr_id_value)
+ return session.ice_driver.find_element_by_id(attr_id_value).text
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Failed to get text of element " + attr_id_value
+ raise Exception(errorMsg, attr_id_value)
+
+ @staticmethod
+ def by_css(attr_css_value, wait_for_page=False):
+ try:
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.css(attr_css_value)
+ return session.ice_driver.find_element_by_css_selector(attr_css_value).text
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Failed to get text of element " + attr_css_value
+ raise Exception(errorMsg, attr_css_value)
+
+ @staticmethod
+ def wysiwyg_element_by_id(attr_id_value):
+ try:
+ Wait.id(attr_id_value)
+ return session.ice_driver.find_element_by_css_selector(
+ "#" + attr_id_value + ".wysiwyg-textarea")
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Failed to get element by id " + attr_id_value
+ raise Exception(errorMsg, attr_id_value)
+
+ @staticmethod
+ def by_name(attr_name_value):
+ try:
+ Wait.name(attr_name_value)
+ return session.ice_driver.find_element_by_name(attr_name_value).text
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Failed to get text of element " + attr_name_value
+ raise Exception(errorMsg, attr_name_value)
+
+ @staticmethod
+ def by_xpath(attr_name_value):
+ try:
+ Wait.xpath(attr_name_value)
+ return session.ice_driver.find_element_by_xpath(attr_name_value).text
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Failed to get text of element " + attr_name_value
+ raise Exception(errorMsg, attr_name_value)
+
+ @staticmethod
+ def value_by_name(attr_name_value):
+ try:
+ Wait.name(attr_name_value)
+ return session.ice_driver.find_element_by_name(attr_name_value).get_attribute("value")
+ except Exception as e:
+ errorMsg = "Failed to get value by name:" + attr_name_value
+ raise Exception(errorMsg, attr_name_value)
+
+ @staticmethod
+ def meta_order_by_id(attr_id_value):
+ try:
+ Wait.id(attr_id_value)
+ return session.ice_driver.find_element_by_id(attr_id_value).get_attribute("meta-order")
+ except Exception as e:
+ errorMsg = "Failed to get meta order by id:" + attr_id_value
+ raise Exception(errorMsg, attr_id_value)
+
+ @staticmethod
+ def is_selected_by_id(attr_id_value, wait_for_page=False):
+ try:
+ if wait_for_page:
+ Wait.page_has_loaded()
+ Wait.id(attr_id_value)
+ return session.ice_driver.find_element_by_id(attr_id_value).is_selected()
+ except Exception as e:
+ errorMsg = "Failed to get if it's selected by id:" + attr_id_value
+ raise Exception(errorMsg, attr_id_value)
diff --git a/services/frontend/base_actions/wait.py b/services/frontend/base_actions/wait.py
new file mode 100644
index 0000000..50eff08
--- /dev/null
+++ b/services/frontend/base_actions/wait.py
@@ -0,0 +1,317 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import time
+
+from selenium.common.exceptions import NoSuchElementException
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support import expected_conditions
+from selenium.webdriver.support.wait import WebDriverWait
+
+from services.constants import Constants
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+
+class Wait:
+
+ @staticmethod
+ def text_by_xpath(xpath, text, wait_for_page=False):
+ try: # Wait 4 seconds for element and compare to expected result.
+ if wait_for_page:
+ Wait.page_has_loaded()
+ WebDriverWait(session.ice_driver, session.wait_until_retires).until(
+ expected_conditions.text_to_be_present_in_element(
+ (By.XPATH, xpath), text)
+ )
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ error_msg = "Text - " + text + " not found in xPath " + xpath
+ raise Exception(error_msg, xpath)
+
+ @staticmethod
+ def text_by_id(element_id, text, wait_for_page=False):
+ try: # Wait 4 seconds for element and compare to expected result.
+ if wait_for_page:
+ Wait.page_has_loaded()
+ WebDriverWait(session.ice_driver, session.wait_until_retires).until(
+ expected_conditions.text_to_be_present_in_element(
+ (By.ID, element_id), text)
+ )
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ error_msg = "Text - " + text + " not found in ID " + element_id
+ raise Exception(error_msg, element_id)
+
+ @staticmethod
+ def text_by_css(css, text, wait_for_page=False):
+ try: # Wait 4 seconds for element and compare to expected result.
+ if wait_for_page:
+ Wait.page_has_loaded()
+ WebDriverWait(session.ice_driver, session.wait_until_retires).until(
+ expected_conditions.text_to_be_present_in_element(
+ (By.CSS_SELECTOR, css), text)
+ )
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ error_msg = "Text - " + text + " not found in CSS - " + css
+ raise Exception(error_msg, e)
+
+ @staticmethod
+ def text_by_name(name, text, wait_for_page=False):
+ try: # Wait 4 seconds for element and compare to expected result.
+ if wait_for_page:
+ Wait.page_has_loaded()
+ WebDriverWait(session.ice_driver, session.wait_until_retires).until(
+ expected_conditions.text_to_be_present_in_element(
+ (By.NAME, name), text)
+ )
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ error_msg = "Text - " + text + " not found by NAME - " + name
+ raise Exception(error_msg, e)
+
+ @staticmethod
+ def id(element_id, wait_for_page=False):
+ try: # Wait 4 seconds for element and compare to expected result.
+ if wait_for_page:
+ Wait.page_has_loaded()
+ WebDriverWait(session.ice_driver, session.wait_until_retires).until(
+ expected_conditions.visibility_of_element_located(
+ (By.ID, element_id))
+ )
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ error_msg = "Didn't find ID " + element_id
+ raise Exception(error_msg, e)
+
+ @staticmethod
+ def css(element_css, wait_for_page=False):
+ try: # Wait 4 seconds for element and compare to expected result.
+ if wait_for_page:
+ Wait.page_has_loaded()
+ WebDriverWait(session.ice_driver, session.wait_until_retires).until(
+ expected_conditions.visibility_of_element_located(
+ (By.CSS_SELECTOR, element_css))
+ )
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ error_msg = "Didn't find CSS Selector " + element_css
+ raise Exception(error_msg, e)
+
+ @staticmethod
+ def is_css_exists(element_css, wait_for_page=False):
+ try: # Wait 4 seconds for element and compare to expected result.
+ if wait_for_page:
+ Wait.page_has_loaded()
+ WebDriverWait(session.ice_driver, session.wait_until_implicit_time).until(
+ expected_conditions.visibility_of_element_located(
+ (By.CSS_SELECTOR, element_css))
+ )
+ return True
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ error_msg = "Didn't find CSS Selector " + element_css
+ return False
+
+ @staticmethod
+ def link_text(link_inner_text, wait_for_page=False):
+ try:
+ if wait_for_page:
+ Wait.page_has_loaded()
+ WebDriverWait(session.ice_driver, session.wait_until_retires).until(
+ expected_conditions.visibility_of_element_located(
+ (By.LINK_TEXT, link_inner_text))
+ )
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ error_msg = "Didn't find LINK TEXT " + link_inner_text
+ raise Exception(error_msg, e)
+
+ @staticmethod
+ def name(element_name, wait_for_page=False):
+ try:
+ if wait_for_page:
+ Wait.page_has_loaded()
+ WebDriverWait(session.ice_driver, session.wait_until_retires).until(
+ expected_conditions.visibility_of_element_located(
+ (By.NAME, element_name))
+ )
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ error_msg = "Didn't find NAME " + element_name
+ raise Exception(error_msg, e)
+
+ @staticmethod
+ def xpath(element_xpath, wait_for_page=False):
+ try:
+ if wait_for_page:
+ Wait.page_has_loaded()
+ WebDriverWait(session.ice_driver, session.wait_until_retires).until(
+ expected_conditions.visibility_of_element_located(
+ (By.XPATH, element_xpath))
+ )
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ error_msg = "Didn't find XPath " + element_xpath
+ raise Exception(error_msg, e)
+
+ @staticmethod
+ def page_has_loaded():
+ countwait_untilelement_to_be_presented_by_id = 0
+ for _ in range(Constants.FEConstants.RETRIES_NUMBER):
+ httpRequests = session.ice_driver.execute_script(
+ 'return window.angular ? window.angular.element("body").injector().get("$http").pendingRequests.length : 1;')
+ if(str(httpRequests) == "0"):
+ time.sleep(session.wait_until_time_pause)
+ return
+ logger.debug(
+ "Checking if {} page is loaded. ".format(session.ice_driver.current_url))
+ time.sleep(session.wait_until_time_pause)
+ countwait_untilelement_to_be_presented_by_id += 1
+
+ raise Exception("Page loading took too much time")
+
+ @staticmethod
+ def modal_to_dissappear():
+ session.ice_driver.implicitly_wait(0)
+ i = 0
+ not_found = False
+ while i < session.wait_until_retires:
+ try:
+ session.ice_driver.find_element_by_css_selector(
+ Constants.Dashboard.Wizard.Open.CSS)
+ except NoSuchElementException:
+ not_found = True
+ try:
+ session.ice_driver.find_element_by_class_name(
+ Constants.Dashboard.Wizard.Open.CLASS_NAME)
+ not_found = False
+ except NoSuchElementException:
+ not_found = True
+
+ if not_found:
+ break
+
+ else:
+ time.sleep(session.wait_until_time_pause)
+ i += 1
+
+ session.ice_driver.implicitly_wait(session.wait_until_implicit_time)
+ if not_found:
+ return True
+ else:
+ raise Exception("waitForModalToDissapper")
+
+ @staticmethod
+ def id_to_dissappear(id_element, wait_for_page=False):
+ if wait_for_page:
+ Wait.page_has_loaded()
+ session.ice_driver.implicitly_wait(0)
+ i = 0
+ not_found = False
+ while i < session.wait_until_retires:
+ try:
+ session.ice_driver.find_element_by_id(id_element)
+ except NoSuchElementException:
+ not_found = True
+
+ if not_found:
+ break
+ else:
+ time.sleep(session.wait_until_time_pause)
+ i += 1
+
+ session.ice_driver.implicitly_wait(session.wait_until_implicit_time)
+ if not_found:
+ return True
+ else:
+ raise Exception(
+ "id_to_dissappear " + id_element + " num of retries = " + str(i))
+
+ @staticmethod
+ def name_to_dissappear(name_element, wait_for_page=False):
+ if wait_for_page:
+ Wait.page_has_loaded()
+ session.ice_driver.implicitly_wait(0)
+ i = 0
+ not_found = False
+ while i < session.wait_until_retires:
+ try:
+ session.ice_driver.find_element_by_name(name_element)
+ except NoSuchElementException:
+ not_found = True
+
+ if not_found:
+ break
+ else:
+ time.sleep(session.wait_until_time_pause)
+ i += 1
+
+ session.ice_driver.implicitly_wait(session.wait_until_implicit_time)
+ if not_found:
+ return True
+ else:
+ raise Exception(
+ "name_to_dissappear " + name_element + " num of retries = " + str(i))
+
+ @staticmethod
+ def css_to_dissappear(css_element):
+ session.ice_driver.implicitly_wait(0)
+ i = 0
+ not_found = False
+ while i < session.wait_until_retires:
+ try:
+ session.ice_driver.find_element_by_css_selector(css_element)
+ except NoSuchElementException:
+ not_found = True
+
+ if not_found:
+ break
+ else:
+ time.sleep(session.wait_until_time_pause)
+ i += 1
+
+ session.ice_driver.implicitly_wait(session.wait_until_implicit_time)
+ if not_found:
+ return True
+ else:
+ raise Exception("css_to_dissappear" + css_element)
diff --git a/services/frontend/fe_checklist.py b/services/frontend/fe_checklist.py
new file mode 100644
index 0000000..75f957a
--- /dev/null
+++ b/services/frontend/fe_checklist.py
@@ -0,0 +1,755 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from django.conf import settings
+from selenium.webdriver.support.ui import Select
+from wheel.signatures import assertTrue
+
+from services.database.db_checklist import DBChecklist
+from services.database.db_user import DBUser
+from services.database.db_virtual_function import DBVirtualFunction
+from services.frontend.base_actions.click import Click
+from services.frontend.base_actions.enter import Enter
+from services.frontend.base_actions.get import Get
+from services.frontend.base_actions.wait import Wait
+from services.frontend.fe_general import FEGeneral
+from services.frontend.fe_overview import FEOverview
+from services.frontend.fe_user import FEUser
+from services.frontend.fe_wizard import FEWizard
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+from tests.uiTests.test_ui_base import *
+
+
+logger = LoggingServiceFactory.get_logger()
+
+
+class FEChecklist:
+
+ assocciatedFileName = None
+
+ @staticmethod
+ def go_to_checklist(engagement_id, cl_uuid):
+ try:
+ Click.id(engagement_id)
+ Click.id("checklist-" + cl_uuid)
+ Wait.id("line-item-description")
+ except Exception as e:
+ errorMsg = "Failed to go to checklist page."
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def create_new_checklist(newObj):
+ try:
+ newObjWithChecklist = None
+ vfName = newObj[0]
+ uuid = newObj[1]
+ inviteEmail = newObj[2]
+ # Fetch one AT&T user ID.
+ vfuuid = DBGeneral.select_where(
+ "uuid", "ice_vf", "name", vfName, 1)
+ engagement_id = DBVirtualFunction.select_eng_uuid(vfName)
+ engLeadEmail = DBUser.select_el_email(vfName)
+ logger.debug("EL email: " + engLeadEmail)
+ engagement_manual_id = DBGeneral.select_where("engagement_manual_id", "ice_engagement", "uuid",
+ engagement_id, 1)
+ # Click on all default next steps
+ myVfName = engagement_manual_id + ": " + vfName
+ actualVfNameid = "clickable-" + myVfName
+ actualVfName = Get.by_id(actualVfNameid)
+ Helper.internal_assert(myVfName, actualVfName)
+ # NEXT STEP ID
+ Click.id(actualVfNameid, wait_for_page=True)
+ FEOverview.complete_defaults_nextsteps(engagement_id)
+ inviterURL = Constants.Default.InviteURL.Signup.TEXT + \
+ vfuuid + "&inviter_uuid=" + uuid + "&email=" + inviteEmail
+# time.sleep(2)
+ FEGeneral.re_open(inviterURL)
+ FEGeneral.form_validate_email(inviteEmail)
+ # Login with EL role
+ FEGeneral.re_open(Constants.Default.LoginURL.TEXT)
+ FEUser.login(engLeadEmail, Constants.Default.Password.TEXT)
+ Wait.id(Constants.Dashboard.Statuses.Title.ID)
+ Wait.id(engagement_manual_id) # cheklist
+ # VALIDATE SCROLLING
+ actualVfName = Get.by_id(actualVfNameid)
+ myVfName = engagement_manual_id + ": " + vfName
+# Wait.id(actualVfNameid)
+ Wait.id(engagement_manual_id, wait_for_page=True)
+ Click.id(actualVfNameid, wait_for_page=True)
+ # Create new checklist
+ checklistName = FEChecklist.create_checklist(
+ engagement_id, vfName, actualVfName, engagement_manual_id)
+ checklistUuid = DBGeneral.select_where(
+ "uuid", "ice_checklist", "name", checklistName, 1)
+ newObjWithChecklist = [checklistUuid, engLeadEmail, engagement_manual_id, actualVfNameid, myVfName,
+ checklistName]
+ return newObjWithChecklist
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Failed to create checklist." + str(e)
+ raise Exception(errorMsg, "create_new_checklist")
+
+ @staticmethod
+ def create_checklist(engagement_id, vfName, actualVfName, engagement_manual_id):
+ try:
+ checklistName = Helper.rand_string("randomString")
+ Wait.id("checklist-plus-" + engagement_id, wait_for_page=True)
+
+ Click.id("checklist-plus-" + engagement_id, wait_for_page=True)
+
+ Helper.internal_assert(
+ "Create Checklist", Get.by_id("modal-header-checklist-15"))
+ # vm.checkListName
+ Enter.text_by_name(
+ "checkListName", checklistName, wait_for_page=True)
+ Wait.xpath("//select")
+
+ Select(session.ice_driver.find_element_by_id(Constants.Template.Subtitle.SelectTemplateTitle.TEXT)
+ ).select_by_visible_text(Constants.Template.Heat.TEXT)
+ Click.id(Constants.Template.Heat.TEXT, wait_for_page=True)
+# Click.css("option.ng-binding.ng-scope")
+ Helper.internal_assert(
+ "Associate Files", Get.by_id("associated-files-title", wait_for_page=True))
+ Click.xpath("//multiselect/div/button", wait_for_page=True)
+ Click.link_text("file0", wait_for_page=True)
+ Click.link_text("file1")
+ Wait.text_by_css(Constants.SubmitButton.CSS, "Create Checklist")
+ Click.id(Constants.Dashboard.LeftPanel.CreateChecklist.ID)
+ Wait.modal_to_dissappear()
+ Wait.id(engagement_manual_id)
+ return checklistName
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Failed to create checklist." + str(e)
+ raise Exception(errorMsg, "create_checklist")
+
+ @staticmethod
+ def update_cl_name_and_associated_files(engagement_manual_id):
+ Click.id("edit-checklist", True)
+ Wait.text_by_id("modal-header-checklist-15", "Update Checklist")
+ newfileName = "file" + Helper.rand_string("randomString")
+ Enter.text_by_xpath("//div[3]/div/div/input", newfileName)
+ updatedFileName = "file2"
+ # Select associated files from multi-select drop-down.
+ Click.xpath("//multiselect/div/button")
+ Click.link_text("file2")
+ Click.css(Constants.SubmitButton.CSS)
+ Wait.id(engagement_manual_id)
+ newFileNames = [newfileName, updatedFileName]
+ return newFileNames
+
+ @staticmethod
+ def update_cl_associated_files(engagement_manual_id):
+ Click.id("edit-checklist", True)
+ Wait.text_by_id("modal-header-checklist-15", "Update Checklist")
+ # Select associated files from multi-select drop-down.
+ Click.xpath("//multiselect/div/button")
+ Click.link_text("file2")
+ Click.xpath("//multiselect/div/button")
+ Click.css(Constants.SubmitButton.CSS)
+ Wait.id(engagement_manual_id, True)
+
+ @staticmethod
+ def add_next_step(checklistName, newObj):
+ Click.id(Constants.Dashboard.Checklist.AddNS.ID, wait_for_page=True)
+ Wait.text_by_css("span.font_header", "Checklist:")
+ Helper.internal_assert("Checklist:", Get.by_css("span.font_header"))
+ Helper.internal_assert("Add Next Steps", Get.by_css("h2"))
+ # First NS
+ Click.id("description")
+ Enter.text_by_id("description", "description of NS")
+ Click.css("div.modal-content")
+ Click.xpath("(//button[@type='button'])[10]")
+ FEChecklist.assocciatedFileName = "file0"
+ Click.link_text(FEChecklist.assocciatedFileName)
+ Click.css("div.modal-content")
+ Click.xpath("(//button[@type='button'])[11]")
+ try:
+ Click.xpath("//div[3]/multiselect/div/ul/li/a")
+ except:
+ Click.link_text("Homer Simpson")
+ Click.css("div.modal-content")
+ count = 0
+ FEWizard.date_picker_add_ns(count)
+ count = +1
+ Click.css("span.add-text")
+ Click.xpath("(//div[@id='description'])[2]")
+ Enter.text_by_xpath(
+ "(//div[@id='description'])[2]", "description of NS2")
+ Click.css("div.modal-content")
+ Click.xpath("(//button[@type='button'])[14]")
+ Click.xpath("(//button[@type='button'])[22]")
+ Click.xpath("//div[3]/div/div[2]/multiselect/div/ul/li[2]/a")
+ Click.css("div.modal-content")
+ Click.xpath("(//button[@type='button'])[23]")
+ Click.css(
+ "div.btn-group.open > ul.dropdown-menu > li.ng-scope > a.ng-binding")
+ Click.link_text("Add Another Next Step")
+ Click.xpath("(//button[@type='button'])[25]")
+ FEWizard.date_picker_add_ns(count)
+ Click.xpath("//div[4]/div/span")
+ Helper.internal_assert("Submit Next Steps", Get.by_id("btn-submit"))
+ Click.id("btn-submit", wait_for_page=True)
+
+ @staticmethod
+ def add_next_step_updated(checklistName, newFileName):
+ Click.id(Constants.Dashboard.Checklist.AddNS.ID)
+ Wait.id(Constants.Dashboard.Modal.CLOSE_BUTTON_ID)
+ Wait.text_by_css("span.font_header.ng-binding", "Checklist:")
+ Wait.text_by_css("h2.ng-binding", "Add Next Steps")
+ # First NS
+ Click.id("description")
+ Enter.text_by_id("description", "description of NS")
+ Click.css("div.modal-content")
+ Click.xpath("(//button[@type='button'])[10]")
+ Click.link_text(newFileName)
+ Click.css("div.modal-content")
+ Click.xpath("(//button[@type='button'])[11]")
+ try:
+ Click.xpath("//div[3]/multiselect/div/ul/li/a")
+ except:
+ Wait.link_text("Homer Simpson")
+ Click.link_text("Homer Simpson")
+ Wait.css("div.modal-content")
+ Click.css("div.modal-content")
+ Wait.xpath("(//button[@type='button'])[12]")
+ count = 0
+ FEWizard.date_picker_add_ns(count)
+ count = +1
+ Click.css("span.add-text")
+ Click.xpath("(//div[@id='description'])[2]")
+ Enter.text_by_xpath(
+ "(//div[@id='description'])[2]", "description of NS2")
+ Click.css("div.modal-content")
+ Click.xpath("(//button[@type='button'])[14]")
+ Click.xpath("(//button[@type='button'])[22]")
+ Click.xpath("//div[3]/div/div[2]/multiselect/div/ul/li[2]/a")
+ Click.css("div.modal-content")
+ Click.xpath("(//button[@type='button'])[23]")
+ Click.css(
+ "div.btn-group.open > ul.dropdown-menu > li.ng-scope > a.ng-binding")
+ Click.link_text("Add Another Next Step")
+ Wait.xpath("(//button[@type='button'])[25]")
+ Click.xpath("(//button[@type='button'])[25]")
+ Wait.xpath("(//button[@type='button'])[24]")
+ FEWizard.date_picker_add_ns(count)
+ Wait.xpath("//div[4]/div/span")
+ Click.xpath("//div[4]/div/span")
+ Wait.id("btn-submit")
+ Wait.text_by_id("btn-submit", "Submit Next Steps")
+# Helper.internal_assert("Submit Next Steps", Get.by_id("btn-submit"))
+ Click.id("btn-submit")
+
+ @staticmethod
+ def approval_state_actions_and_validations(checklistName, newObj, state):
+ # REWVIEW STEPS AND VALIDATIONS
+ try:
+ Wait.id("checklist-main-section")
+ Wait.text_by_id(
+ Constants.Dashboard.Checklist.Name.ID, checklistName)
+ try:
+ if settings.DATABASE_TYPE == 'local':
+ Wait.text_by_css(
+ "h2.ng-binding", "Section 1: Parameter Specification")
+ Helper.internal_assert(
+ "Parameters", Get.by_css("span.col-md-9.ng-binding"))
+ Helper.internal_assert(
+ "String parameters", Get.by_xpath("//li[2]/span[2]"))
+ Helper.internal_assert(
+ "Numeric parameters", Get.by_xpath("//li[3]/span[2]"))
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert("Section 2: External References",
+ Get.by_xpath("//li[2]/h2"))
+ # //li[2]/ul/li/span[2] #//ul[@id='line-item-list']/li[2]/ul/li/span[2]
+ Helper.internal_assert(
+ "Normal references", Get.by_xpath("//li[2]/ul/li/span[2]"))
+ Helper.internal_assert(
+ "VF image", Get.by_xpath("//li[2]/ul/li[2]/span[2]"))
+ except:
+ if settings.DATABASE_TYPE == 'local':
+ Wait.text_by_css(
+ "h2.ng-binding", "Section 1: External References")
+ try:
+ Helper.internal_assert(
+ "Normal references", Get.by_css("span.col-md-9.ng-binding"))
+ except:
+ if "VF image" in Get.by_xpath("//li[2]/span[2]"):
+ logger.debug("All Ok")
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Section 2: Parameter Specification", Get.by_xpath("//li[2]/h2"))
+ try:
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "1.1 - Parameters", Get.by_xpath("//header/h2"))
+ except:
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "1.1 - Normal References", Get.by_xpath("//header/h2"))
+ if settings.DATABASE_TYPE == 'local':
+ elementTxt = Get.by_id("line-item-description")
+ Helper.internal_assert(
+ "Numeric parameters should include range and/or allowed values.", elementTxt)
+ Helper.internal_assert("Audit Logs", Get.by_css("h3.col-md-12"))
+ localLogText = "local log"
+ Enter.text_by_id("new-audit-log-text", localLogText)
+ Helper.internal_assert(
+ "Add Log Entry", Get.by_id("submit-new-audit-lop-text"))
+ Click.id("submit-new-audit-lop-text")
+ vfName = newObj[0]
+ engLeadFullName = DBUser.get_el_name(vfName)
+ Helper.internal_assert(localLogText, Get.by_css(
+ Constants.Dashboard.Checklist.AuditLog.LastLocalAuditLog.CSS))
+ try:
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Parameters", Get.by_xpath("//li[2]/ul/li/span[2]"))
+ except:
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Numeric parameters", Get.by_xpath("//li[2]/ul/li/span[2]"))
+
+# if Wait.css(Constants.Dashboard.Checklist.LineItem.Deny.CSS) or
+# Wait.css(Constants.Dashboard.Checklist.LineItem.Approve.CSS):
+ session.run_negative(lambda: Wait.css(Constants.Dashboard.Checklist.LineItem.Deny.CSS) or Wait.css(
+ Constants.Dashboard.Checklist.LineItem.Approve.CSS), "Buttons displayed for Admin it's NOT work")
+# logger.debug("Buttons displayed for Admin it's NOT work")
+# else:
+# print("Buttons not displayed for Admin it's work")
+ if state == "APPROVAL":
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Audit Log (6)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ else:
+ Helper.internal_assert(
+ "Audit Log (7)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ if state == "HANDOFF":
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Audit Log (8)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ else:
+ Helper.internal_assert(
+ "Audit Log (9)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ Click.id(Constants.Dashboard.Checklist.AuditLog.ID)
+ Wait.text_by_xpath("//span[2]", checklistName)
+ engLeadFullName = DBUser.select_el_email(vfName)
+ Enter.text_by_xpath("//textarea", "zdfgsdyh")
+ Click.css(Constants.SubmitButton.CSS)
+ Wait.modal_to_dissappear()
+ if state == "APPROVAL":
+ if settings.DATABASE_TYPE == 'local':
+ Wait.text_by_id(
+ Constants.Dashboard.Checklist.AuditLog.ID, "Audit Log (7)")
+ else:
+ Wait.text_by_id(
+ Constants.Dashboard.Checklist.AuditLog.ID, "Audit Log (8)")
+ if state == "HANDOFF":
+ if settings.DATABASE_TYPE == 'local':
+ Wait.text_by_id(
+ Constants.Dashboard.Checklist.AuditLog.ID, "Audit Log (9)")
+ else:
+ Wait.text_by_id(
+ Constants.Dashboard.Checklist.AuditLog.ID, "Audit Log (10)")
+ if state == "APPROVAL":
+ Wait.text_by_xpath("//button[3]", "Add Next Steps")
+ Wait.text_by_id(Constants.Dashboard.Checklist.Reject.ID,
+ Constants.Dashboard.Checklist.Reject.Modal.Button.TEXT)
+ Wait.text_by_xpath(
+ "//div[@id='state-actions']/button", "Approve")
+ if state == "HANDOFF":
+ Wait.text_by_xpath(
+ "//div[@id='state-actions']/button", "Handoff complete?")
+ logger.debug("ALL VALIDATION PASS FOR STATE : " + state)
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ logger.error(
+ state + " state FAILED CONNECT TO STAGING MANUAL AND VERIFY WHY! ")
+ errorMsg = "approval_state_actions_and_validations FAILED because : " + \
+ str(e)
+ raise Exception(errorMsg, "approval_state_actions_and_validations")
+
+ @staticmethod
+ def review_state_actions_and_validations(checklistName, vfName, state):
+ try:
+ # REWVIEW STEPS AND VALIDATIONS
+ Wait.id("checklist-main-section")
+ Wait.text_by_id(
+ Constants.Dashboard.Checklist.Name.ID, checklistName)
+ try:
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Section 1: Parameter Specification", Get.by_css("h2.ng-binding"))
+ Helper.internal_assert(
+ "Parameters", Get.by_css("span.col-md-9.ng-binding"))
+ Helper.internal_assert(
+ "String parameters", Get.by_xpath("//li[2]/span[2]"))
+ Helper.internal_assert(
+ "Numeric parameters", Get.by_xpath("//li[3]/span[2]"))
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Section 2: External References", Get.by_xpath("//li[2]/h2"))
+ Helper.internal_assert(
+ "Normal references", Get.by_name("Normal references"))
+ Helper.internal_assert(
+ "VF image", Get.by_name("Normal references"))
+ except:
+ try:
+ Helper.internal_assert(
+ "Section 1: External References", Get.by_css("h2.ng-binding"))
+ except:
+ Helper.internal_assert(
+ "Section 1: Scaling Considerations", Get.by_css("h2.ng-binding"))
+ try:
+ Helper.internal_assert(
+ "Normal references", Get.by_css("span.col-md-9.ng-binding"))
+ except:
+ if "VF image" in Get.by_xpath("//li[2]/span[2]"):
+ logger.debug("All Ok")
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Section 2: Parameter Specification", Get.by_xpath("//li[2]/h2"))
+ Click.name("VF image")
+ Click.name("Normal references")
+ try:
+ Helper.internal_assert(
+ "1.1 - Parameters", Get.by_xpath("//header/h2"))
+ except:
+ text = Get.by_name("Normal references")
+ Helper.internal_assert("Normal references", text)
+ Helper.internal_assert("Audit Logs", Get.by_css("h3.col-md-12"))
+ localLogText = "local log"
+ Enter.text_by_id("new-audit-log-text", localLogText)
+ Helper.internal_assert(
+ "Add Log Entry", Get.by_id("submit-new-audit-lop-text"))
+ Click.id("submit-new-audit-lop-text")
+ # Validate Local AuditLog
+ engLeadFullName = DBUser.get_el_name(vfName)
+ Helper.internal_assert(
+ engLeadFullName, Get.by_xpath("//ul[@id='audit-log-list']/li/h4"))
+ Helper.internal_assert(localLogText, Get.by_css(
+ Constants.Dashboard.Checklist.AuditLog.LastLocalAuditLog.CSS))
+ if settings.DATABASE_TYPE == 'local':
+ try:
+ Helper.internal_assert(
+ "Parameters", Get.by_xpath("//li[2]/ul/li/span[2]"))
+ except:
+ Helper.internal_assert(
+ "Numeric parameters", Get.by_xpath("//li[2]/ul/li/span[2]"))
+ Click.name("Normal references")
+ Wait.css(Constants.Dashboard.Checklist.LineItem.Deny.CSS)
+ Wait.css(Constants.Dashboard.Checklist.LineItem.Approve.CSS)
+ Click.css(Constants.Dashboard.Checklist.LineItem.Approve.CSS)
+ # NOT LOCAL
+ if settings.DATABASE_TYPE != 'local':
+ checklistUuid = DBChecklist.get_recent_checklist_uuid(
+ checklistName)[0]
+ DBChecklist.update_all_decisions_to_approve(checklistUuid)
+ # NOT LOCAL
+
+ Click.css(".line-item-row span.manual")
+ print("click on V button approve of decision in state = " + state)
+ try:
+ Wait.css("li.not-relevant-btn")
+ except:
+ Wait.xpath("//aside/header/ul/li")
+ if state == "review":
+ Wait.id("edit-checklist")
+ if state == "PEER":
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Audit Log (4)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ else:
+ Helper.internal_assert(
+ "Audit Log (5)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ if state == "review":
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Audit Log (2)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ else:
+ Helper.internal_assert(
+ "Audit Log (3)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ if state == "APPROVAL":
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Audit Log (8)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ else:
+ Helper.internal_assert(
+ "Audit Log (9)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ Click.id(
+ Constants.Dashboard.Checklist.AuditLog.ID, wait_for_page=True)
+ Wait.text_by_xpath("//span[2]", checklistName)
+ Enter.text_by_xpath("//textarea", "zdfgsdyh")
+ Click.css(Constants.SubmitButton.CSS)
+ Wait.modal_to_dissappear()
+ if state == "review":
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Audit Log (3)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ else:
+ Helper.internal_assert(
+ "Audit Log (4)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ if state == "PEER":
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Audit Log (5)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ else:
+ Helper.internal_assert(
+ "Audit Log (6)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ if state == "APPROVAL":
+ if settings.DATABASE_TYPE == 'local':
+ Helper.internal_assert(
+ "Audit Log (9)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ else:
+ Helper.internal_assert(
+ "Audit Log (10)", Get.by_id(Constants.Dashboard.Checklist.AuditLog.ID))
+ # Validate Buttons
+ if settings.DATABASE_TYPE != 'local':
+ FEGeneral.refresh()
+ engagement_id = DBVirtualFunction.select_eng_uuid(vfName)
+ engLeadEmail = DBUser.select_el_email(vfName)
+ logger.debug("EL email: " + engLeadEmail)
+ engagement_manual_id = DBGeneral.select_where("engagement_manual_id", "ice_engagement",
+ "uuid", engagement_id, 1)
+ # Click on all default next steps
+ myVfName = engagement_manual_id + ": " + vfName
+ actualVfNameid = "clickable-" + myVfName
+ Click.id(actualVfNameid)
+ Click.id("checklist-" + checklistUuid)
+ Helper.internal_assert(
+ "Add Next Steps", Get.by_xpath("//button[3]"))
+ Wait.text_by_id(Constants.Dashboard.Checklist.Reject.ID,
+ Constants.Dashboard.Checklist.Reject.Modal.Button.TEXT, wait_for_page=True)
+ Helper.internal_assert(
+ "Approve", Get.by_xpath("//div[@id='state-actions']/button"))
+ logger.debug("ALL VALIDATION PASS FOR STATE: " + state)
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "review_state_actions_and_validations FAILED because: " + \
+ str(e)
+ raise Exception(errorMsg, "review_state_actions_and_validations")
+ logger.error(
+ state + " state FAILED CONNECT TO STAGING MANUAL AND VERIFY WHY!")
+ raise
+
+ @staticmethod
+ def reject(rejectMsg=None):
+ try:
+ Click.id(
+ Constants.Dashboard.Checklist.Reject.ID, wait_for_page=True)
+ if rejectMsg:
+ Enter.text_by_name(
+ Constants.Dashboard.Checklist.Reject.Modal.Comment.NAME, rejectMsg, wait_for_page=True)
+ Click.id(
+ Constants.Dashboard.Checklist.Reject.Modal.Button.ID, wait_for_page=True)
+ except Exception as e:
+ errorMsg = "Failed to reject checklist."
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def add_line_item_audit_log():
+ try:
+ log_txt = Helper.rand_string("randomString")
+ Enter.text_by_id("new-audit-log-text", log_txt, wait_for_page=True)
+ Click.id("submit-new-audit-lop-text")
+ Wait.text_by_css(
+ Constants.Dashboard.Checklist.AuditLog.LastLocalAuditLog.CSS, log_txt, wait_for_page=True)
+ return log_txt
+ except Exception as e:
+ errorMsg = "Failed to add audit log to line item."
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def click_on_checklist(user_content, checklistName, checklist_uuid=None):
+ FEOverview.click_on_vf(user_content)
+ if checklist_uuid is None:
+ checklist_uuid = DBGeneral.select_where_not_and_order_by_desc(
+ 'uuid', Constants.DBConstants.IceTables.CHECKLIST, 'name', checklistName, 'state', Constants.ChecklistStates.Archive.TEXT, 'create_time')[0]
+ Click.id("checklist-" + checklist_uuid)
+
+ @staticmethod
+ def validate_reject_is_enabled():
+ return Wait.id(Constants.Dashboard.Checklist.Reject.ID, wait_for_page=True)
+
+ @staticmethod
+ def cl_to_next_stage(actualVfNameid):
+ Click.xpath("//div[@id='state-actions']/button", wait_for_page=True)
+ Wait.id(actualVfNameid, wait_for_page=True)
+ session.run_negative(lambda: Wait.css(
+ Constants.Default.BlockUI.CSS), "Error: CL to next stage failed.")
+
+ @staticmethod
+ def search_by_vfname_for_not_local(user_content):
+ vfFullName = user_content[
+ 'engagement_manual_id'] + ": " + user_content['vfName']
+ if settings.DATABASE_TYPE != 'local':
+ Enter.text_by_id(
+ Constants.Dashboard.LeftPanel.SearchBox.ID, user_content['vfName'])
+ Click.css(Constants.Dashboard.LeftPanel.SearchBox.Results.CSS)
+ Wait.text_by_id(
+ Constants.Dashboard.Overview.Title.ID, vfFullName)
+
+ @staticmethod
+ def search_by_manual_id(manual_id):
+ Enter.text_by_id(
+ Constants.Dashboard.LeftPanel.SearchBox.ID, manual_id, wait_for_page=True)
+ Click.css(
+ Constants.Dashboard.LeftPanel.SearchBox.Results.CSS, wait_for_page=True)
+ Wait.id(Constants.Dashboard.Overview.Title.ID)
+
+ @staticmethod
+ def reject_checklist(newObj, checklistName):
+ Click.xpath("//button[2]")
+ vfName = newObj[0]
+ engLeadFullName = DBUser.get_el_name(vfName)
+ Enter.text_by_name(
+ Constants.Dashboard.Checklist.Reject.Modal.Comment.NAME, "Reject state By :" + engLeadFullName)
+ Helper.internal_assert(
+ "Checklist: " + checklistName, Get.by_css("span.state-title.ng-binding"))
+ Wait.text_by_id(Constants.Dashboard.Checklist.Reject.Modal.Button.ID,
+ Constants.Dashboard.Checklist.Reject.Modal.Button.TEXT)
+ Click.id(Constants.Dashboard.Checklist.Reject.Modal.Button.ID)
+ Wait.modal_to_dissappear()
+
+ @staticmethod
+ def add_nsteps(checklistUuid, actualVfNameid, myVfName, checklistName, newFileNames):
+ Click.id(actualVfNameid, wait_for_page=True)
+ checklistUuid = DBChecklist.select_where_cl_not_archive(
+ "uuid", "ice_checklist", "name", newFileNames[0], 1)
+ Click.id("checklist-" + checklistUuid, wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.Checklist.Name.ID, newFileNames[0])
+ FEChecklist.add_next_step_updated(checklistName, newFileNames[1])
+ # vALIDATE SCROLLING
+ actualVfNameid = "clickable-" + myVfName
+ actualVfName = Get.by_id(actualVfNameid, wait_for_page=True)
+ if actualVfName != '':
+ Helper.internal_assert(myVfName, actualVfName)
+
+ @staticmethod
+ def validate_multi_eng(user_content, checklist_content, newEL_content, actualVfNameid):
+ query = "UPDATE ice_user_profile SET role_id=2 WHERE email = '" + \
+ str(newEL_content['email']) + "';"
+ DBGeneral.update_by_query(query)
+ FEWizard.invite_team_members_modal(newEL_content['email'])
+ # Fetch one AT&T user ID.
+ enguuid = DBGeneral.select_where(
+ "uuid", "ice_engagement", "engagement_manual_id", user_content['engagement_manual_id'], 1)
+ invitation_token = DBUser.select_invitation_token(
+ "invitation_token", "ice_invitation", "engagement_uuid", enguuid, newEL_content['email'], 1)
+ URL = Constants.Default.InviteURL.Login.TEXT + invitation_token
+ FEGeneral.re_open(URL)
+ FEUser.login(newEL_content[
+ 'email'], Constants.Default.Password.TEXT, expected_element=actualVfNameid)
+ Click.id(actualVfNameid, wait_for_page=True)
+ count = None
+ try:
+ session.ice_driver.find_element_by_id(
+ "checklist-" + checklist_content['uuid'])
+ count += 1
+ except:
+ logger.debug(
+ "check list not visible for EL invited : " + str(newEL_content['email']))
+ assertTrue(count == None)
+ query = "UPDATE ice_user_profile SET role_id=1 WHERE email = '" + \
+ str(newEL_content['email']) + "';"
+ DBGeneral.update_by_query(query)
+
+ @staticmethod
+ def create_cl_without_files(user_content):
+ FEOverview.click_on_vf(user_content)
+ Click.id("checklist-plus-" + user_content['engagement_uuid'])
+ Wait.id(Constants.Dashboard.Modal.CLOSE_BUTTON_ID)
+ checklistName = "NoAssociatedFiles" + \
+ Helper.rand_string("randomString")
+ Enter.text_by_name("checkListName", checklistName)
+ Wait.xpath("//select")
+ if settings.DATABASE_TYPE == 'local':
+ Select(session.ice_driver.find_element_by_xpath("//select")
+ ).select_by_visible_text(Constants.Template.Heat.TEXT)
+ else:
+ Click.xpath("//select")
+ Click.xpath("//option[2]")
+ Click.id(Constants.Dashboard.LeftPanel.CreateChecklist.ID)
+ Wait.text_by_id(Constants.Dashboard.Checklist.Name.ID, checklistName)
+
+ @staticmethod
+ def validate_audit_log(log_txt):
+ audit_log_list_text = Get.by_id(
+ Constants.Dashboard.Checklist.AuditLog.AuditLogList.ID, wait_for_page=True)
+ try:
+ log_txt in audit_log_list_text
+ logger.debug("validate_audit_log PASS")
+ except Exception as e:
+ errorMsg = "Failed in validate_audit_log"
+ raise Exception(errorMsg)
+
+ @staticmethod
+ def get_to_create_new_ns_modal():
+ Click.id(Constants.Dashboard.Checklist.AddNS.ID,
+ wait_for_page=True)
+ Wait.text_by_css(Constants.Dashboard.Checklist.AddNS.CSS,
+ Constants.Dashboard.Checklist.TITLE)
+ Helper.internal_assert(Constants.Dashboard.Checklist.TITLE, Get.by_css(
+ Constants.Dashboard.Checklist.AddNS.CSS))
+ Helper.internal_assert(
+ Constants.Dashboard.Checklist.AddNS.TITLE,
+ Get.by_css(Constants.FEGeneral.CSS.H2))
+
+ @staticmethod
+ def get_to_create_new_ns_modal_via_overview():
+ Click.id(Constants.Dashboard.Overview.NextSteps.Add.ID,
+ wait_for_page=True)
+ Wait.text_by_css(Constants.Dashboard.Checklist.AddNS.CSS,
+ Constants.Dashboard.Overview.NextSteps.Add.TITLE)
+ Helper.internal_assert(
+ Constants.Dashboard.Checklist.AddNS.TITLE,
+ Get.by_css(Constants.FEGeneral.CSS.H2))
+
+ @staticmethod
+ def get_jenkins_log():
+ Click.id(Constants.Dashboard.Checklist.JenkinsLog.ID, True)
+ Wait.text_by_id(
+ Constants.Dashboard.Checklist.JenkinsLog.Modal.Title.ID,
+ Constants.Dashboard.Checklist.JenkinsLog.Modal.Title.TEXT, True)
+ log = Get.by_id(
+ Constants.Dashboard.Checklist.JenkinsLog.Modal.Body.ID, True)
+ Helper.assertTrue(Constants.Dashboard.Checklist.JenkinsLog.Modal.Body.TEXT_SAMPLE in log,
+ "Jenkins log could not be viewed.")
+ Click.id(Constants.Dashboard.Modal.CLOSE_BUTTON_ID)
+ return log
+
diff --git a/services/frontend/fe_checklist_template.py b/services/frontend/fe_checklist_template.py
new file mode 100644
index 0000000..19e91aa
--- /dev/null
+++ b/services/frontend/fe_checklist_template.py
@@ -0,0 +1,254 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from selenium.webdriver.common.action_chains import ActionChains
+from selenium.webdriver.common.keys import Keys
+
+from services.api.api_virtual_function import APIVirtualFunction
+from services.constants import Constants
+from services.database.db_checklist import DBChecklist
+from services.database.db_user import DBUser
+from services.frontend.base_actions.click import Click
+from services.frontend.base_actions.enter import Enter
+from services.frontend.base_actions.get import Get
+from services.frontend.base_actions.wait import Wait
+from services.frontend.fe_checklist import FEChecklist
+from services.frontend.fe_general import FEGeneral
+from services.frontend.fe_overview import FEOverview
+from services.frontend.fe_user import FEUser
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class FEChecklistTemplate:
+
+ @staticmethod
+ def basic_admin_navigation():
+ FEUser.login(
+ Constants.Users.Admin.EMAIL, Constants.Default.Password.TEXT)
+ FEUser.go_to_admin()
+
+ @staticmethod
+ def click_on_template_name_on_navigation(template_name, text):
+ Wait.text_by_name(template_name, text, wait_for_page=True)
+ Click.name(template_name, wait_for_page=True)
+
+ @staticmethod
+ def click_on_save_and_assert_success_msg():
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.SAVE_BTN_ID, wait_for_page=True)
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.APPROVE_BTN_ID, wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.LeftPanel.EditChecklistTemplate.SUCCESS_ID,
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.SUCCESS_SAVE_MSG)
+
+ @staticmethod
+ def click_on_disabled_save_and_assert_for_promp_msg():
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.SAVE_BTN_ID)
+ session.run_negative(lambda: Click.id(Constants.Dashboard.LeftPanel.EditChecklistTemplate.APPROVE_BTN_ID),
+ "Ooops modal window is opened although 'Save' button should have been disabled")
+
+ @staticmethod
+ def save_with_no_changes():
+ Wait.text_by_id(Constants.Dashboard.LeftPanel.EditChecklistTemplate.SAVE_BTN_ID,
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.SAVE_BTN)
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.SAVE_BTN_ID, wait_for_page=True)
+ Wait.text_by_name(Constants.Dashboard.LeftPanel.EditChecklistTemplate.HEAT,
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.HEAT)
+ Wait.text_by_id(Constants.Dashboard.LeftPanel.EditChecklistTemplate.APPROVE_BTN_TITLE_ID,
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.APPROVE_BTN_TITLE_TEXT)
+ Wait.text_by_id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.APPROVE_BTN_ID, "Yes")
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.APPROVE_BTN_ID, wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.LeftPanel.EditChecklistTemplate.SUCCESS_ID,
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.CL_TEMPLATE_SAVED_TXT)
+
+ @staticmethod
+ def discard_checklist_after_modification():
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.FIRST_SECTION_ID, wait_for_page=True)
+ Enter.text_by_id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.FIRST_SECTION_INPUT_ID, "ttttttt", wait_for_page=True)
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.FIRST_SECTION_ID)
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.REJECT_BTN_ID)
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.APPROVE_BTN_ID, wait_for_page=True)
+ Wait.text_by_id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.SUCCESS_ID, "All changes discarded.")
+
+ @staticmethod
+ def edit_template_and_save():
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.FIRST_SECTION_ID)
+ Enter.text_by_id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.FIRST_SECTION_INPUT_ID, "Ros Is My Mentor")
+ FEChecklistTemplate.click_on_save_and_assert_success_msg()
+
+ @staticmethod
+ def del_lineitem_and_save():
+ Click.id(Constants.Dashboard.LeftPanel.EditChecklistTemplate.FIRST_SECTION_ID, wait_for_page=True)
+ Enter.text_by_id(Constants.Dashboard.LeftPanel.EditChecklistTemplate.FIRST_SECTION_INPUT_ID,
+ "Ros Is My Mentor", wait_for_page=True)
+ Click.id(Constants.Dashboard.LeftPanel.EditChecklistTemplate.FIRST_SECTION_ID)
+ FEChecklistTemplate.click_on_save_and_assert_success_msg()
+
+ @staticmethod
+ def add_lineitem_and_save():
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.ADD_LINE_ITEM_BTN, wait_for_page=True)
+ Click.xpath("//li[@id='select-lineitem-btn-0.1']/span[2]")
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.EDIT_LINE_ITEM_BTN)
+ Enter.text_by_id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.EDIT_LINE_ITEM_NAME, "xxx")
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.EDIT_LINE_ITEM_BTN, wait_for_page=True)
+ FEChecklistTemplate.click_on_save_and_assert_success_msg()
+
+ @staticmethod
+ def edit_description_lineitem_and_save():
+ isBold = False
+ desc = Helper.rand_string("randomString")
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.FIRST_LINE_ITEM_ID)
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.EDIT_LINE_ITEM_BTN)
+ Enter.text_by_id(Constants.Dashboard.LeftPanel.EditChecklistTemplate.EDIT_LINE_ITEM_NAME,
+ Helper.rand_string("randomString"))
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.EDIT_LINE_ITEM_DESC)
+ editor_element = Get.wysiwyg_element_by_id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.LINE_ITEM_DESC_TEXT_BOX)
+ editor_element.clear()
+ editor_element.send_keys(desc)
+ Wait.page_has_loaded()
+ actionChains = ActionChains(session.ice_driver)
+ actionChains.double_click(editor_element).perform()
+ Wait.page_has_loaded()
+ Click.xpath(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.WYSIWYG_BUTTON_BOLD)
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.EDIT_LINE_ITEM_BTN, wait_for_page=True)
+ isBold = Wait.is_css_exists("b")
+ while not isBold:
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.EDIT_LINE_ITEM_BTN, wait_for_page=True)
+ actionChains.double_click(editor_element).perform()
+ Click.xpath(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.WYSIWYG_BUTTON_BOLD, wait_for_page=True)
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.EDIT_LINE_ITEM_BTN, wait_for_page=True)
+ isBold = Wait.is_css_exists("b")
+ if isBold:
+ FEChecklistTemplate.click_on_save_and_assert_success_msg()
+ FEGeneral.refresh()
+ Click.name(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.HEAT, wait_for_page=True)
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.FIRST_LINE_ITEM_ID, wait_for_page=True)
+ Wait.css("b")
+ Wait.text_by_css("b", desc, wait_for_page=True)
+
+ @staticmethod
+ def rollback_add_lineitem_and_save():
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.DELETE_LINE_ITEM)
+ FEChecklistTemplate.click_on_save_and_assert_success_msg()
+ FEChecklistTemplate.rollback_to_heat_teampleate()
+
+ @staticmethod
+ def add_lineitem_and_check_db():
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.FIRST_SECTION_ID)
+ Enter.text_by_id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.FIRST_SECTION_INPUT_ID, "Ros Is My Mentor")
+ FEChecklistTemplate.click_on_save_and_assert_success_msg()
+ result = DBChecklist.checkChecklistIsUpdated()
+ Helper.internal_not_equal(result, None)
+
+ @staticmethod
+ def check_cl_after_lineitem_added():
+ template_name = Constants.Dashboard.LeftPanel.EditChecklistTemplate.HEAT
+ user_content = APIVirtualFunction.create_engagement()
+ FEUser.login(
+ Constants.Users.Admin.EMAIL, Constants.Default.Password.TEXT)
+ vfName = user_content['vfName']
+ engagement_id = DBChecklist.fetchEngByVfName(vfName)
+ engLeadEmail = DBUser.select_el_email(vfName)
+ engagement_manual_id = DBChecklist.fetchEngManIdByEngUuid(
+ engagement_id)
+ myVfName = engagement_manual_id + ": " + vfName
+ FEOverview.click_on_vf(user_content)
+ FEGeneral.re_open(Constants.Default.LoginURL.TEXT)
+ FEUser.login(
+ engLeadEmail, Constants.Default.Password.TEXT, engagement_manual_id)
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.DASHBOARD_ID)
+ Enter.text_by_id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.SEARCH_ENG_ID, vfName)
+ Click.id("test_" + vfName)
+ checklistName = FEChecklist.create_checklist(
+ engagement_id, vfName, None, engagement_manual_id)
+ FEUser.go_to_admin()
+ result = DBChecklist.fetchChecklistByName(checklistName)
+ FEUser.go_to_admin()
+ FEChecklistTemplate.click_on_template_name_on_navigation(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.HEAT, template_name)
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.EDIT_LINE_ITEM_BTN)
+ Enter.text_by_id(Constants.Dashboard.LeftPanel.EditChecklistTemplate.EDIT_LINE_ITEM_NAME,
+ "test_lineitem_added_and_audit_log_on_dupl_cl-NAME")
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.EDIT_LINE_ITEM_BTN)
+ FEChecklistTemplate.click_on_save_and_assert_success_msg()
+ Click.id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.DASHBOARD_ID)
+ Enter.text_by_id(
+ Constants.Dashboard.LeftPanel.EditChecklistTemplate.SEARCH_ENG_ID, vfName)
+ Click.id("test_" + vfName)
+ Click.id("checklist-" + str(result))
+ Helper.internal_assert(
+ "1. automation", session.ice_driver.find_element_by_xpath("//li[@id='']").text)
diff --git a/services/frontend/fe_cms.py b/services/frontend/fe_cms.py
new file mode 100644
index 0000000..a86626e
--- /dev/null
+++ b/services/frontend/fe_cms.py
@@ -0,0 +1,157 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from services.constants import Constants
+from services.database.db_cms import DBCMS
+from services.frontend.base_actions.click import Click
+from services.frontend.base_actions.enter import Enter
+from services.frontend.base_actions.wait import Wait
+from services.frontend.fe_dashboard import FEDashboard
+from services.frontend.fe_general import FEGeneral
+from services.frontend.fe_user import FEUser
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class FECms:
+
+ @staticmethod
+ def validate_5_last_announcement_displayed(listOfTitleAnDescriptions, user_content, last_title):
+ last_description = listOfTitleAnDescriptions[
+ len(listOfTitleAnDescriptions) - 1][1]
+ Wait.text_by_id(Constants.Toast.CMS_ID, last_title + ".")
+ FEDashboard.open_announcement()
+ Wait.text_by_id(Constants.Cms.Toast_title_id, last_title)
+ Wait.text_by_id(Constants.Cms.Toast_description, last_description)
+ DBCMS.update_X_days_back_post(last_title, xdays=3)
+ Click.id(Constants.Cms.Test_addDT_close_modal_button)
+ FEUser.logout()
+ # Validate Announcement TOAST not displayed
+ FEUser.login(user_content['email'], Constants.Default.Password.TEXT)
+ session.run_negative(lambda: Wait.text_by_id(Constants.Cms.Toast_title_id, last_title),
+ "Last Announcement displayed in News & Announcements sections %s" % last_title)
+
+ @staticmethod
+ def validate_grandchild_page(parent_title, child_title, grand_child_title, description):
+ Click.id(Constants.Cms.Documentation)
+ Click.id(parent_title)
+ Click.id(child_title)
+ Click.id(grand_child_title)
+ Wait.text_by_id("center-" + grand_child_title, grand_child_title)
+ page_id = DBCMS.get_last_inserted_page_id()
+ Wait.text_by_id(page_id, description)
+
+ @staticmethod
+ def announcement_validate_toast(title, description, user_content):
+ Wait.text_by_id(Constants.Toast.CMS_ID, title + ".")
+ FEDashboard.open_announcement()
+ Wait.text_by_id(Constants.Cms.Toast_title_id, title)
+ Wait.text_by_id(Constants.Cms.Toast_description, description)
+ Click.id(Constants.Cms.Test_addDT_close_modal_button)
+ Click.css("button.close")
+ FEUser.logout()
+ FEUser.login(user_content['email'], Constants.Default.Password.TEXT)
+ # Validate Announcement displayed in News & Announcements sections
+ session.run_negative(lambda: FEDashboard.open_announcement(
+ ), "Announcement toast disappear after 2 days %s" % title)
+ Wait.text_by_id(title, title)
+ Wait.text_by_id(description, description)
+
+ @staticmethod
+ def search_documentation_title(title, user_content):
+ FEDashboard.open_documentation(title)
+ Wait.text_by_id(title, title)
+ logger.debug("Search Documentation by title")
+ Enter.text_by_id(Constants.Cms.SearchDocumentation, title, wait_for_page=True)
+ Wait.text_by_id(title, title)
+ Click.id(title, wait_for_page=True)
+ Wait.text_by_id(title, title)
+ logger.debug("Documentation found (searched by title)")
+
+ @staticmethod
+ def search_documentation_content(title, content):
+ FEDashboard.open_documentation(title)
+ Wait.text_by_id(title, title)
+ logger.debug("Search Documentation by content")
+ Enter.text_by_id(Constants.Cms.SearchDocumentation, content, wait_for_page=True)
+ Wait.text_by_id(title, title)
+ Click.id(title, wait_for_page=True)
+ Wait.text_by_css(Constants.Cms.DocumentationPageContent, content)
+ logger.debug("Documentation found (searched by content)")
+
+ @staticmethod
+ def validate_expired_post_Announcement(title, description):
+ Wait.text_by_id(Constants.Toast.CMS_ID, title + ".")
+ FEDashboard.open_announcement()
+ Wait.text_by_id(Constants.Cms.Toast_title_id, title)
+ Wait.text_by_id(Constants.Cms.Toast_description, description)
+ DBCMS.update_X_days_back_post(title, xdays=3)
+ Click.id(Constants.Cms.Test_addDT_close_modal_button)
+ FEGeneral.refresh()
+ session.run_negative(lambda: Wait.text_by_id(
+ Constants.Toast.CMS_ID, title + "."), "Announcement toast not disappear after 2 days %s" % title)
+
+ @staticmethod
+ def validate_page(title, description):
+ Click.id(Constants.Cms.Documentation)
+ Click.id(title)
+ Wait.text_by_id("center-" + title, title)
+ page_id = DBCMS.get_last_inserted_page_id()
+ Wait.text_by_id(page_id, description)
+
+ @staticmethod
+ def validate_FAQ(description):
+ Wait.text_by_id(Constants.Cms.Tooltip_title, "Did you know?")
+ Wait.text_by_id(Constants.Cms.Tooltip_description, description)
+
+ @staticmethod
+ def validate_news(title, description):
+ Wait.text_by_id(title, title)
+ Wait.text_by_id(description, description)
+ Click.id(title)
+ Wait.text_by_id(Constants.Cms.Toast_title_id, title)
+ Wait.text_by_id(Constants.Cms.Toast_description, description)
+
+ @staticmethod
+ def validae_announcement(title, description):
+ Wait.text_by_id(Constants.Toast.CMS_ID, title + ".")
+ FEDashboard.open_announcement()
+ Wait.text_by_id(Constants.Cms.Toast_title_id, title)
+ Wait.text_by_id(Constants.Cms.Toast_description, description)
diff --git a/services/frontend/fe_dashboard.py b/services/frontend/fe_dashboard.py
new file mode 100644
index 0000000..0df66d4
--- /dev/null
+++ b/services/frontend/fe_dashboard.py
@@ -0,0 +1,289 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from selenium.webdriver.support.ui import Select
+
+from services.constants import Constants
+from services.database.db_user import DBUser
+from services.frontend.base_actions.click import Click
+from services.frontend.base_actions.enter import Enter
+from services.frontend.base_actions.get import Get
+from services.frontend.base_actions.wait import Wait
+from services.frontend.fe_general import FEGeneral
+from services.frontend.fe_overview import FEOverview
+from services.frontend.fe_user import FEUser
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+
+class FEDashboard:
+
+ @staticmethod
+ def open_announcement():
+ try:
+ Click.id("read-more-button")
+ except Exception as e:
+ errorMsg = "Failed to go to Announcement page."
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def open_documentation(title):
+ try:
+ Click.id("documentation", wait_for_page=True)
+ Wait.id("search-doc")
+ Wait.text_by_id(title, title, wait_for_page=True)
+ except Exception as e:
+ errorMsg = "Failed to go to Announcement page."
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def validate_filtering_by_stage(user_content, stage):
+ FEGeneral.re_open(Constants.Default.LoginURL.TEXT)
+ # Validate Scrolling #
+ FEUser.login(user_content['el_email'], Constants.Default.Password.TEXT)
+ FEOverview.click_on_vf(user_content)
+ Click.id(Constants.Dashboard.Statuses.ID, wait_for_page=True)
+ Wait.text_by_id("dashboard-title", "Statuses", wait_for_page=True)
+ Wait.id("search-filter-stage")
+ Select(session.ice_driver.find_element_by_id(
+ "search-filter-stage")).select_by_visible_text(stage)
+ Wait.id(
+ Constants.Dashboard.Statuses.ExportExcel.ID, wait_for_page=True)
+ engLeadID = DBUser.select_user_native_id(user_content['el_email'])
+ # Query for fetching count of rows per stage.
+ countOfEngInStagePerUser = DBUser.select_user_engagements_by_stage(
+ stage, engLeadID)
+ # Calculate number of pages #
+ NUM_OF_RESULTS_PER_PAGES = 8
+ number_of_pages = countOfEngInStagePerUser // NUM_OF_RESULTS_PER_PAGES
+ logger.debug("Number of pages: " + str(number_of_pages))
+ if (countOfEngInStagePerUser % NUM_OF_RESULTS_PER_PAGES != 0):
+ number_of_pages += 1
+ logger.debug("number_of_pages " + str(number_of_pages)) # Scroll #
+ Wait.id("engagements-pagination", wait_for_page=True)
+ element = session.ice_driver.find_element_by_id(
+ "engagements-pagination")
+ element.location_once_scrolled_into_view
+ Click.link_text(str(number_of_pages), wait_for_page=True)
+
+ @staticmethod
+ def validate_filtering_by_stage_with_page_ids(user_content, stage):
+ FEOverview.click_on_vf(user_content)
+ Click.id(Constants.Dashboard.Statuses.ID)
+ # Stage Active Validation #
+ Wait.text_by_id("dashboard-title", "Statuses")
+ Wait.id(Constants.Dashboard.Statuses.FilterDropdown.ID)
+ Select(session.ice_driver.find_element_by_id(
+ Constants.Dashboard.Statuses.FilterDropdown.ID)).select_by_visible_text("Intake")
+ Wait.page_has_loaded()
+ Select(session.ice_driver.find_element_by_id(
+ Constants.Dashboard.Statuses.FilterDropdown.ID)).select_by_visible_text(stage)
+ Wait.id(
+ Constants.Dashboard.Statuses.ExportExcel.ID, wait_for_page=True)
+ countIdsActive = 0
+ engLeadID = DBUser.select_user_native_id(user_content['el_email'])
+ countOfEngInStagePerUser = DBUser.select_user_engagements_by_stage(
+ stage, engLeadID) # Calculate number of pages #
+ NUM_OF_RESULTS_PER_PAGES = 8
+ number_of_pages = countOfEngInStagePerUser // NUM_OF_RESULTS_PER_PAGES
+ if countOfEngInStagePerUser <= NUM_OF_RESULTS_PER_PAGES:
+ number_of_pages = 1
+ if number_of_pages == 1:
+ # Count all engagements on current page
+ logger.debug("Number of pages: " + str(number_of_pages))
+ ids = session.ice_driver.find_elements_by_xpath('//*[@id]')
+ for ii in ids:
+ if "starred-" in ii.get_attribute('id'):
+ # Print ii.tag_name (id name as string).
+ logger.debug(ii.get_attribute('id'))
+ countIdsActive += 1
+ Wait.id(Constants.Dashboard.Statuses.ExportExcel.ID)
+ if countIdsActive == countOfEngInStagePerUser:
+ logger.debug("result right")
+ else:
+ if countOfEngInStagePerUser % NUM_OF_RESULTS_PER_PAGES != 0:
+ number_of_pages += 1
+ logger.debug("number_of_pages " + str(number_of_pages))
+ # Scroll #
+ Wait.id("engagements-pagination")
+ element = session.ice_driver.find_element_by_id(
+ "engagements-pagination")
+ element.location_once_scrolled_into_view
+ if number_of_pages > 1:
+ Click.link_text(str(number_of_pages), wait_for_page=True)
+
+ @staticmethod
+ def validate_statistics_by_stages(user_content):
+ # Validate Scrolling #
+ FEOverview.click_on_vf(user_content)
+ Click.id(Constants.Dashboard.Statuses.ID)
+ Wait.text_by_id("dashboard-title", "Statuses")
+ Wait.css(Constants.Dashboard.Statuses.Statistics.FilterDropdown.CSS)
+ Select(session.ice_driver.find_element_by_css_selector(
+ Constants.Dashboard.Statuses.Statistics.FilterDropdown.CSS)).select_by_visible_text("All")
+ engLeadID = DBUser.select_user_native_id(user_content['el_email'])
+ countOfEngInStagePerUser = DBUser.select_all_user_engagements(
+ engLeadID) # Scroll #
+ Wait.text_by_id(
+ Constants.Dashboard.Statuses.Statistics.EngagementsNumber.ID,
+ str(countOfEngInStagePerUser), wait_for_page=True)
+ element = session.ice_driver.find_element_by_id(
+ Constants.Dashboard.Statuses.Statistics.EngagementsNumber.ID)
+ # Stage Active Validation #
+ element.location_once_scrolled_into_view
+ Wait.css(
+ Constants.Dashboard.Statuses.Statistics.FilterDropdown.CSS, wait_for_page=True)
+ Select(session.ice_driver.find_element_by_css_selector(
+ Constants.Dashboard.Statuses.Statistics.FilterDropdown.CSS)).select_by_visible_text("Active")
+ countOfEngInStagePerUser = DBUser.select_user_engagements_by_stage(
+ "Active", engLeadID)
+ Wait.text_by_id(
+ Constants.Dashboard.Statuses.Statistics.EngagementsNumber.ID, str(countOfEngInStagePerUser), wait_for_page=True)
+
+ @staticmethod
+ def search_by_vf(user_content):
+ engName = user_content[
+ 'engagement_manual_id'] + ": " + user_content['vfName']
+ engSearchID = "eng-" + engName
+ FEGeneral.re_open_not_clean_cache(Constants.Default.DashbaordURL.TEXT)
+ logger.debug("Search engagement by engagement_manual_id")
+ Enter.text_by_id(Constants.Dashboard.Statuses.SearchBox.ID,
+ user_content['engagement_manual_id'], wait_for_page=True)
+ eng_manual_id = user_content['engagement_manual_id'] + ":"
+ Wait.text_by_id(engSearchID, eng_manual_id)
+
+ @staticmethod
+ def search_in_left_searchbox_by_param(manual_id, vf_name, param):
+ myVfName = manual_id + ": " + vf_name
+ Enter.text_by_xpath(
+ Constants.Dashboard.LeftPanel.SearchBox.Results.XPATH, param)
+ Wait.text_by_css(
+ Constants.Dashboard.LeftPanel.SearchBox.Results.CSS, myVfName)
+ Click.css(Constants.Dashboard.LeftPanel.SearchBox.Results.CSS)
+
+ @staticmethod
+ def check_vnf_version(user_content):
+ current_vnf_value = Get.by_css(
+ "#progress_bar_" + user_content['engagement_manual_id'] + " ." + Constants.Dashboard.Overview.Progress.VnfVersion.CLASS, wait_for_page=True)
+ Helper.internal_assert(current_vnf_value, user_content['vnf_version'])
+
+ @staticmethod
+ def search_in_dashboard(user_content, vfcName, users):
+ engName = user_content[
+ 'engagement_manual_id'] + ": " + user_content['vfName']
+ engSearchID = "eng-" + engName
+ for user in users:
+ FEGeneral.re_open(Constants.Default.LoginURL.TEXT)
+ logger.debug("Login with user " + user)
+ FEUser.login(user, Constants.Default.Password.TEXT)
+ logger.debug("Search engagement by engagement_manual_id")
+ Enter.text_by_id(
+ Constants.Dashboard.Statuses.SearchBox.ID, user_content['engagement_manual_id'])
+ eng_manual_id = user_content['engagement_manual_id'] + ":"
+ Wait.text_by_id(engSearchID, eng_manual_id)
+ logger.debug("Engagement found (searched by engagement_manual_id)")
+ FEGeneral.refresh()
+ logger.debug("Search engagement by VF name")
+ # Search by VF name.
+ Enter.text_by_id(
+ Constants.Dashboard.Statuses.SearchBox.ID, user_content['vfName'])
+ Wait.text_by_id(engSearchID, eng_manual_id)
+ logger.debug("Engagement found (searched by VF name)")
+ FEGeneral.refresh()
+ logger.debug("Search engagement by VFC")
+ # Search by VFC.
+ Enter.text_by_id(
+ Constants.Dashboard.Statuses.SearchBox.ID, vfcName)
+ Wait.text_by_id(engSearchID, eng_manual_id)
+ logger.debug("Engagement found (searched by VFC)")
+ FEGeneral.refresh()
+ logger.debug("Negative search: search by random string")
+ # Search by VFC.
+ Enter.text_by_id(Constants.Dashboard.Statuses.SearchBox.ID,
+ "RND_STR_" + Helper.rand_string("randomString"))
+ Wait.text_by_id("search-results", "Export to Excel >>")
+
+ @staticmethod
+ def check_if_the_eng_of_NS_is_the_correct_one(user_content):
+ logger.debug(" > Check if the engagement of NS is the correct one")
+ engName = user_content[
+ 'engagement_manual_id'] + ": " + user_content['vfName']
+ Wait.text_by_name(
+ user_content['engagement_manual_id'], "Engagement - " + engName)
+ return engName
+
+ @staticmethod
+ def check_if_creator_of_NS_is_the_EL(user_content):
+ logger.debug(
+ " > Check if creator of NS is the EL " + user_content['el_name'])
+ if (user_content['el_name'] not in Get.by_name("creator-full-name-" + user_content['el_name'])):
+ logger.error("EL is not the creator of the NS according to UI.")
+ raise
+
+ @staticmethod
+ def statuses_search_vf(engagement_manual_id, vf_name):
+ engName = engagement_manual_id + ": " + vf_name
+ # Search by VF name.
+ Enter.text_by_id(
+ Constants.Dashboard.Statuses.SearchBox.ID, vf_name, wait_for_page=True)
+ Wait.id("eng-" + engName, wait_for_page=True)
+ Click.id("eng-" + engName, wait_for_page=True)
+ Wait.text_by_id(
+ Constants.Dashboard.Overview.Title.ID, engName, wait_for_page=True)
+
+ @staticmethod
+ def go_to_main_dashboard():
+ Click.id(Constants.Dashboard.Statuses.ID)
+
+ @staticmethod
+ def click_on_dashboard_and_validate_statistics(is_negative):
+ # Click.id(Constants.Dashboard.Default.DASHBOARD_ID)
+ Wait.page_has_loaded()
+ if is_negative:
+ session.run_negative(lambda: Wait.id(
+ Constants.Dashboard.Default.STATISTICS), "Negative test failed at Statistics appears")
+ else:
+ Wait.id(Constants.Dashboard.Default.STATISTICS)
+
+ @staticmethod
+ def click_on_create_vf():
+ Click.id(Constants.Dashboard.LeftPanel.AddEngagement.ID)
diff --git a/services/frontend/fe_detailed_view.py b/services/frontend/fe_detailed_view.py
new file mode 100644
index 0000000..bf9a5bf
--- /dev/null
+++ b/services/frontend/fe_detailed_view.py
@@ -0,0 +1,359 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import time
+
+from selenium.webdriver.support.ui import Select
+
+from services.constants import Constants
+from services.database.db_general import DBGeneral
+from services.frontend.base_actions.click import Click
+from services.frontend.base_actions.enter import Enter
+from services.frontend.base_actions.get import Get
+from services.frontend.base_actions.wait import Wait
+from services.frontend.fe_dashboard import FEDashboard
+from services.frontend.fe_general import FEGeneral
+from services.frontend.fe_user import FEUser
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+
+class FEDetailedView:
+
+ @staticmethod
+ def search_vf_and_go_to_detailed_view(engagement_manual_id, vf_name):
+ engName = engagement_manual_id + ": " + vf_name
+ detailed_view_id = Constants.Dashboard.DetailedView.ID + engName
+ FEDashboard.statuses_search_vf(engagement_manual_id, vf_name)
+ Click.id(detailed_view_id, wait_for_page=True)
+ return detailed_view_id
+
+ @staticmethod
+ def update_aic_version():
+ Click.id(
+ Constants.Dashboard.DetailedView.ValidationDetails.PLUS, wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.Modal.TITLE_ID,
+ Constants.Dashboard.DetailedView.ValidationDetails.TITLE, wait_for_page=True)
+ Select(session.ice_driver.find_element_by_id(Constants.Dashboard.DetailedView.AIC.Dropdown.ID)
+ ).select_by_visible_text(Constants.Dashboard.DetailedView.ValidationDetails.TargetAICVersion.AIC3)
+ Click.xpath("//option[3]", wait_for_page=True)
+ Click.id(
+ Constants.Dashboard.DetailedView.ValidationDetails.SAVE, wait_for_page=True)
+
+ @staticmethod
+ def open_validation_details():
+ Click.id(
+ Constants.Dashboard.DetailedView.ValidationDetails.PLUS, wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.Modal.TITLE_ID,
+ Constants.Dashboard.DetailedView.ValidationDetails.TITLE, wait_for_page=True)
+
+ @staticmethod
+ def save_validation_details():
+ Click.id(
+ Constants.Dashboard.DetailedView.ValidationDetails.SAVE, wait_for_page=True)
+
+ @staticmethod
+ def update_target_lab_entry():
+ Click.id(
+ Constants.Dashboard.DetailedView.TargetLabEntry.CHANGE, wait_for_page=True)
+ Enter.date_picker(
+ '#lab-entry-date', 'vm.targetLabDate', wait_for_page=True)
+ Click.css(
+ Constants.Dashboard.DetailedView.TargetLabEntry.INPUT_CSS, wait_for_page=True)
+ Click.css(Constants.SubmitButton.CSS, wait_for_page=True)
+ actualDate = Get.by_css(
+ Constants.Dashboard.DetailedView.TargetLabEntry.CONTENT_CSS, wait_for_page=True)
+ return str(actualDate)
+
+ @staticmethod
+ def validate_target_lab_entry(date):
+ Wait.text_by_css(Constants.Dashboard.DetailedView.TargetLabEntry.CSS,
+ Constants.Dashboard.DetailedView.TargetLabEntry.TEXT, wait_for_page=True)
+ actualDate = Get.by_css(
+ Constants.Dashboard.DetailedView.TargetLabEntry.CONTENT_CSS)
+ Helper.internal_assert(actualDate, date)
+
+ @staticmethod
+ def update_ecomp_release(EcompName):
+ count = 0
+ try:
+ Click.id(Constants.Dashboard.DetailedView.ValidationDetails.PLUS)
+ Wait.text_by_id(Constants.Dashboard.Modal.TITLE_ID,
+ Constants.Dashboard.DetailedView.ValidationDetails.TITLE, wait_for_page=True)
+ Click.id(
+ Constants.Dashboard.DetailedView.ECOMP.Dropdown.ID, wait_for_page=True)
+ Select(session.ice_driver.find_element_by_id(
+ Constants.Dashboard.DetailedView.ECOMP.Dropdown.ID)).select_by_visible_text(EcompName)
+ Click.id(Constants.Dashboard.DetailedView.ValidationDetails.ECOMPRelease.ID_ECOMP +
+ EcompName, wait_for_page=True)
+ count += 1
+ Wait.id(Constants.Dashboard.DetailedView.ValidationDetails.ECOMPRelease.ID_ECOMP +
+ Constants.Dashboard.DetailedView.ValidationDetails.ECOMPRelease.UNKNOW, wait_for_page=True)
+ Select(session.ice_driver.find_element_by_id(Constants.Dashboard.DetailedView.ECOMP.Dropdown.ID)
+ ).select_by_visible_text(Constants.Dashboard.DetailedView.ValidationDetails.ECOMPRelease.UNKNOW)
+ Click.id(Constants.Dashboard.DetailedView.ValidationDetails.ECOMPRelease.ID_ECOMP +
+ Constants.Dashboard.DetailedView.ValidationDetails.ECOMPRelease.UNKNOW, wait_for_page=True)
+ count += 1
+ Click.id(
+ Constants.Dashboard.DetailedView.ValidationDetails.SAVE, wait_for_page=True)
+ Helper.internal_assert(count, 2)
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "Failed in update_ecomp_release ."
+ raise Exception(errorMsg)
+
+ @staticmethod
+ def update_vf_version():
+ try:
+ Click.id(
+ Constants.Dashboard.DetailedView.ValidationDetails.PLUS, wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.Modal.TITLE_ID,
+ Constants.Dashboard.DetailedView.ValidationDetails.TITLE, wait_for_page=True)
+ newVFVersionName = "newVFVersionName-" + \
+ Helper.rand_string("randomString")
+ Click.id(
+ Constants.Dashboard.DetailedView.ValidationDetails.VFVersion.ID_VERSION)
+ Enter.text_by_id(
+ Constants.Dashboard.DetailedView.ValidationDetails.VFVersion.ID_VERSION, newVFVersionName, wait_for_page=True)
+ Click.id(
+ Constants.Dashboard.DetailedView.ValidationDetails.SAVE, wait_for_page=True)
+ return newVFVersionName
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "Failed in update_ecomp_release ."
+ raise Exception(errorMsg)
+
+ @staticmethod
+ def validate_aic_version():
+ FEGeneral.refresh()
+ Wait.id(
+ Constants.Dashboard.DetailedView.AIC.ID + "3.0", wait_for_page=True)
+
+ @staticmethod
+ def validate_ecomp_version():
+ FEGeneral.refresh()
+ Wait.id(Constants.Dashboard.DetailedView.ECOMP.ID +
+ Constants.Dashboard.DetailedView.ValidationDetails.ECOMPRelease.UNKNOW, wait_for_page=True)
+
+ @staticmethod
+ def validate_vf_version(newVFVersionName):
+ FEGeneral.refresh()
+ Wait.id(Constants.Dashboard.DetailedView.ValidationDetails.VFVersion.VF_VERSION_ID +
+ newVFVersionName, wait_for_page=True)
+
+ @staticmethod
+ def validate_all_titles_on_dv_form():
+ Wait.text_by_id(Constants.Dashboard.DetailedView.DeploymentTarget.ID,
+ Constants.Dashboard.DetailedView.DeploymentTarget.TEXT, wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.DetailedView.VirtualFunctionComponents.ID,
+ Constants.Dashboard.DetailedView.VirtualFunctionComponents.TEXT)
+ Wait.text_by_id(Constants.Dashboard.DetailedView.TargetLabEntry.ID,
+ Constants.Dashboard.DetailedView.TargetLabEntry.TEXT)
+ Wait.text_by_id(Constants.Dashboard.DetailedView.ValidationDetails.ID,
+ Constants.Dashboard.DetailedView.ValidationDetails.TEXT)
+ Wait.text_by_id(Constants.Dashboard.DetailedView.ValidationDetails.TargetAICVersion.ID,
+ Constants.Dashboard.DetailedView.ValidationDetails.TargetAICVersion.TEXT)
+ Wait.text_by_id(Constants.Dashboard.DetailedView.ValidationDetails.ECOMPRelease.ID,
+ Constants.Dashboard.DetailedView.ValidationDetails.ECOMPRelease.TEXT)
+ Wait.text_by_id(Constants.Dashboard.DetailedView.ValidationDetails.VFVersion.ID,
+ Constants.Dashboard.DetailedView.ValidationDetails.VFVersion.TEXT, wait_for_page=True)
+
+ @staticmethod
+ def add_deployment_target(user_content):
+ Click.id(Constants.Dashboard.DetailedView.TargetLabEntry.Add.ID)
+ Wait.text_by_id(Constants.Dashboard.Modal.TITLE_ID,
+ Constants.Dashboard.DetailedView.DeploymentTarget.TITLE)
+ # FIXME: empty drop-down, tests will fail.
+ Select(session.ice_driver.find_element_by_xpath(
+ "//select")).select_by_visible_text("Lisle (DPA3)")
+ Click.id(
+ Constants.Dashboard.DetailedView.DeploymentTarget.SAVE, wait_for_page=True)
+ Wait.text_by_css(
+ Constants.Dashboard.DetailedView.DeploymentTarget.CSS, "Lisle (DPA3)", wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.DetailedView.AIC.ID +
+ user_content['target_aic'], user_content['target_aic'])
+ e2edate = FEGeneral.date_short_formatter()
+ Wait.text_by_css(
+ Constants.Dashboard.DetailedView.TargetLabEntry.CONTENT_CSS, e2edate)
+
+ @staticmethod
+ def remove_deployment_target(user_content):
+ Wait.text_by_id(
+ "visible-dts-Lisle (DPA3)", "Lisle (DPA3)", wait_for_page=True)
+ dt_site_id = DBGeneral.select_query(
+ "SELECT uuid FROM public.ice_deployment_target_site where name = 'Lisle (DPA3)'")
+ Click.id("visible-dts-Lisle (DPA3)")
+ Wait.id(
+ Constants.Dashboard.DetailedView.DeploymentTarget.ID_REMOVE_DTS + dt_site_id)
+ Click.id(Constants.Dashboard.DetailedView.DeploymentTarget.ID_REMOVE_DTS +
+ dt_site_id, wait_for_page=True)
+ session.run_negative(lambda: Wait.text_by_id(
+ "visible-dts-Lisle (DPA3)", "Lisle (DPA3)", wait_for_page=True), "Negative test failed at wait text Lisle (DPA3)")
+
+ @staticmethod
+ def add_vfc():
+ vfcName = "VFC-" + Helper.rand_string("randomString")
+ Click.id(Constants.Dashboard.DetailedView.VFC.Add.ID)
+ Enter.text_by_name("name", vfcName)
+ session.ice_driver.find_element_by_name("extRefID").click()
+ Enter.text_by_name("extRefID", Helper.rand_string("randomNumber"))
+ Select(session.ice_driver.find_element_by_id(
+ Constants.Dashboard.DetailedView.VFC.Choose_Company.ID)).select_by_visible_text("AT&T")
+ Click.id(Constants.Dashboard.DetailedView.VFC.Save_button.ID)
+ return vfcName
+
+ @staticmethod
+ def add_vfcs(name, extRefID):
+ Click.id(
+ Constants.Dashboard.DetailedView.VFC.Add.ID, wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.Modal.TITLE_ID,
+ "Add Virtual Function Components (VFCs)")
+ Enter.text_by_name("name", name)
+ Click.name("extRefID", wait_for_page=True)
+ Enter.text_by_name("extRefID", extRefID, wait_for_page=True)
+ Select(session.ice_driver.find_element_by_id(
+ Constants.Dashboard.DetailedView.VFC.Choose_Company.ID)).select_by_visible_text("Amdocs")
+ Wait.text_by_css("span.add-text", "Add VFC", wait_for_page=True)
+ Click.css("span.add-text", wait_for_page=True)
+ logger.debug("Add VFC no.2")
+ Enter.text_by_xpath(
+ "//div[2]/ng-form/div/input", "djoni2", wait_for_page=True)
+ Enter.text_by_xpath("//div[2]/ng-form/div[2]/input", "loka2")
+ Enter.text_by_xpath("//div[2]/ng-form/div[4]/input", "companyManual2")
+ Click.id(
+ Constants.Dashboard.DetailedView.VFC.Save_button.ID, wait_for_page=True)
+
+ @staticmethod
+ def remove_vfc(user_content):
+ vf_id = DBGeneral.select_where(
+ "uuid", "ice_vf", "name", user_content['vfName'], 1)
+ djoni_uuid = None
+ counter = 0
+ while not djoni_uuid and counter <= Constants.DBConstants.RETRIES_NUMBER:
+ time.sleep(session.wait_until_time_pause_long)
+ djoni_uuid = DBGeneral.select_where_and(
+ "uuid", "ice_vfc", "vf_id", vf_id, "name", "djoni", 1)
+ logger.debug("Checklist state not changed yet (%s of %s)" % (
+ counter, Constants.DBConstants.RETRIES_NUMBER))
+ counter += 1
+ logger.debug("VFC_UUID was successfully selecteded : " +
+ djoni_uuid + ", and was verified over the DB")
+ Wait.text_by_id(Constants.Dashboard.DetailedView.VFC.ID +
+ "djoni", "djoni (loka)", wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.DetailedView.VFC.ID +
+ "djoni2", "djoni2 (loka2)", wait_for_page=True)
+ Click.id(
+ Constants.Dashboard.DetailedView.VFC.ID + "djoni", wait_for_page=True)
+ Click.id(Constants.Dashboard.DetailedView.VFC.Remove.ID +
+ djoni_uuid, wait_for_page=True)
+
+ @staticmethod
+ def validate_deployment_targets(user_content, users):
+ for user in users:
+ FEGeneral.re_open(Constants.Default.LoginURL.TEXT)
+ logger.debug("Login with user " + user)
+ FEUser.login(user, Constants.Default.Password.TEXT)
+ FEDetailedView.search_vf_and_go_to_detailed_view(
+ user_content['engagement_manual_id'], user_content['vfName'])
+ Wait.id(
+ Constants.Dashboard.DetailedView.DeploymentTarget.AddDeploymentTargetButton.ID)
+
+ @staticmethod
+ def add_remove_deployment_targets(user_content, users):
+ for user in users:
+ FEGeneral.re_open(Constants.Default.LoginURL.TEXT)
+ logger.debug("Login with user " + user)
+ FEUser.login(user, Constants.Default.Password.TEXT)
+ FEDetailedView.search_vf_and_go_to_detailed_view(
+ user_content['engagement_manual_id'], user_content['vfName'])
+ FEDetailedView.add_deployment_target(user_content)
+ FEDetailedView.remove_deployment_target(user_content)
+
+ @staticmethod
+ def validate_negative_role_for_deployment_targets(user_content, users):
+ for user in users:
+ FEGeneral.re_open(Constants.Default.LoginURL.TEXT)
+ logger.debug("Login with user " + user)
+ FEUser.login(user, Constants.Default.Password.TEXT)
+ FEDetailedView.search_vf_and_go_to_detailed_view(
+ user_content['engagement_manual_id'], user_content['vfName'])
+ session.run_negative(lambda: Click.id(Constants.Dashboard.DetailedView.DeploymentTarget.AddDeploymentTargetButton.ID),
+ "Negative test failed at click_on_ deployment-targets with user %s" % user)
+
+ @staticmethod
+ def click_on_update_aic_version():
+ Click.id(
+ Constants.Dashboard.DetailedView.ValidationDetails.PLUS, wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.Modal.TITLE_ID,
+ Constants.Dashboard.DetailedView.ValidationDetails.TITLE, wait_for_page=True)
+
+ @staticmethod
+ def click_on_update_ecomp_release():
+ Click.id(
+ Constants.Dashboard.DetailedView.ValidationDetails.PLUS, wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.Modal.TITLE_ID,
+ Constants.Dashboard.DetailedView.ValidationDetails.TITLE, wait_for_page=True)
+
+ @staticmethod
+ def select_aic_version_from_list(aic_version):
+ Select(session.ice_driver.find_element_by_id(
+ Constants.Dashboard.DetailedView.AIC.Dropdown.ID)).select_by_visible_text(aic_version)
+
+ @staticmethod
+ def compare_aic_selected_version(expected_aic_version):
+ Helper.internal_assert(Get.by_id(
+ Constants.Dashboard.DetailedView.AIC.ID + expected_aic_version), expected_aic_version)
+
+ @staticmethod
+ def compare_selected_ecomp_release(expected_ecomp_release):
+ Helper.internal_assert(Get.by_id(
+ Constants.Dashboard.DetailedView.ECOMP.ID + expected_ecomp_release), expected_ecomp_release)
+
+ @staticmethod
+ def validate_deprecated_aic_version_in_dropdown(expected_aic_version):
+ Helper.internal_assert(Get.by_id(Constants.Dashboard.DetailedView.AIC.Dropdown.UniversalVersion.ID %
+ expected_aic_version), "AIC " + expected_aic_version + " - Deprecated")
+
+ @staticmethod
+ def validate_deprecated_ecomp_release_in_dropdown(expected_ecomp_release):
+ Helper.internal_assert(Get.by_id(Constants.Dashboard.DetailedView.ECOMP.Dropdown.UniversalRelease.ID %
+ expected_ecomp_release), expected_ecomp_release + " - Deprecated")
diff --git a/services/frontend/fe_general.py b/services/frontend/fe_general.py
new file mode 100644
index 0000000..c6832cb
--- /dev/null
+++ b/services/frontend/fe_general.py
@@ -0,0 +1,261 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import json
+import time
+
+from django.conf import settings
+from selenium.webdriver.support.select import Select
+
+from services.constants import Constants
+from services.frontend.base_actions.click import Click
+from services.frontend.base_actions.enter import Enter
+from services.frontend.base_actions.get import Get
+from services.frontend.base_actions.wait import Wait
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class FEGeneral(Helper):
+
+ @staticmethod
+ def date_formatter():
+ d = int(time.strftime("%d"))
+ if (d == 1 or d == 21 or d == 31):
+ d = str(d) + "st"
+ elif (d == 2 or d == 22):
+ d = str(d) + "nd"
+ elif (d == 3 or d == 23):
+ d = str(d) + "rd"
+ else:
+ d = str(d) + "th"
+ return time.strftime("%A %B " + d + " %Y")
+
+ @staticmethod
+ def date_short_formatter():
+ return time.strftime("%-m" + "/" + "%-d" + "/" + "%y")
+
+ @staticmethod
+ def re_open(reopen_url):
+ try:
+ logger.debug("Reopen URL: " + reopen_url)
+ session.ice_driver.get('javascript:localStorage.clear();')
+ session.ice_driver.get('javascript:sessionStorage.clear();')
+ session.ice_driver.delete_all_cookies()
+ # Open FireFox with requested URL.
+ session.ice_driver.get("about:blank")
+ # Open FireFox with requested URL.
+ session.ice_driver.get(reopen_url)
+ session.ice_driver.maximize_window()
+ Wait.page_has_loaded()
+ except Exception as e:
+ errorMsg = "Could not reopen requested page"
+ raise Exception(errorMsg, reopen_url)
+
+ @staticmethod
+ def re_open_not_clean_cache(url):
+ try:
+ # Open FireFox with requested URL.
+ session.ice_driver.get(url)
+ session.ice_driver.maximize_window()
+ except:
+ errorMsg = "Could not reopen requested page"
+ raise Exception(errorMsg, url)
+ logger.debug("Moving to next test case")
+
+ @staticmethod
+ def refresh():
+ try: # Click on element in UI, by CSS locator.
+ session.ice_driver.refresh()
+ Wait.page_has_loaded()
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Could not refresh the page."
+ logger.error(errorMsg)
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def select_vendor_from_list(vendor):
+ Wait.name(Constants.Signup.Company.NAME)
+ Select(session.ice_driver.find_element_by_name(
+ Constants.Signup.Company.NAME)).select_by_visible_text(vendor)
+
+ @staticmethod
+ def go_to_signup_from_login():
+ Click.link_text(Constants.Login.Signup.LINK_TEXT, wait_for_page=True)
+ Wait.text_by_css(
+ Constants.Signup.Title.CSS, Constants.Signup.Title.TEXT, wait_for_page=True)
+
+ @staticmethod
+ def form_enter_name(name):
+ Enter.text_by_name(Constants.Signup.FullName.NAME, name)
+
+ @staticmethod
+ def form_enter_email(email):
+ Enter.text_by_name(Constants.Signup.Email.NAME, email)
+
+ @staticmethod
+ def form_enter_phone(phone):
+ Enter.text_by_name(Constants.Signup.Phone.NAME, phone)
+
+ @staticmethod
+ def form_enter_password(password):
+ Enter.text_by_name(Constants.Signup.Password.NAME, password)
+
+ @staticmethod
+ def form_check_checkbox(xpath):
+ Click.xpath(xpath)
+
+ @staticmethod
+ def click_on_submit():
+ Click.css(Constants.SubmitButton.CSS)
+
+ @staticmethod
+ def go_to_login_from_signup():
+ Click.link_text(Constants.Signup.HaveAccount.LINK_TEXT)
+ Wait.text_by_css(Constants.Login.Title.CSS, Constants.Login.Title.TEXT)
+
+ @staticmethod
+ def verify_toast_message(expected_message):
+ Wait.text_by_id(
+ Constants.Toast.ID, expected_message, wait_for_page=True)
+
+ @staticmethod
+ def form_validate_name(name):
+ name_in_ui = Get.value_by_name(
+ Constants.Dashboard.Avatar.Account.FullName.NAME)
+ Helper.internal_assert(name, name_in_ui)
+
+ @staticmethod
+ def form_validate_email(email):
+ email_in_ui = Get.value_by_name(
+ Constants.Dashboard.Avatar.Account.Email.NAME)
+ Helper.internal_assert(email, email_in_ui)
+
+ @staticmethod
+ def form_validate_phone(phone):
+ phone_in_ui = Get.value_by_name(
+ Constants.Dashboard.Avatar.Account.Phone.NAME)
+ Helper.internal_assert(phone, phone_in_ui)
+
+ @staticmethod
+ def form_validate_company(company):
+ company_in_ui = Get.value_by_name(
+ Constants.Dashboard.Avatar.Account.Company.NAME)
+ Helper.internal_assert(company, company_in_ui)
+
+ @staticmethod
+ def form_validate_ssh(key):
+ key_in_ui = Get.value_by_name(
+ Constants.Dashboard.Avatar.Account.SSHKey.NAME)
+ Helper.internal_assert(key, key_in_ui)
+
+ @staticmethod
+ def go_to_reset_password_from_login():
+ Click.link_text(Constants.Login.ResetPassword.LINK_TEXT)
+
+ @staticmethod
+ def send_reset_password(email):
+ FEGeneral.go_to_reset_password_from_login()
+ Wait.text_by_css(
+ Constants.ResetPassword.Title.CSS, Constants.ResetPassword.Title.TEXT)
+ Enter.text_by_name(Constants.ResetPassword.Email.NAME, email)
+ Wait.text_by_css(
+ Constants.SubmitButton.CSS, Constants.ResetPassword.Button.TEXT)
+ Click.css(Constants.SubmitButton.CSS)
+ Wait.text_by_id(
+ Constants.Toast.ID, Constants.ResetPassword.Toast.Success.TEXT)
+ logger.debug(Constants.ResetPassword.Toast.Success.TEXT)
+
+ @staticmethod
+ def verify_home_elements():
+ Wait.text_by_id(Constants.Home.Title.ID, Constants.Home.Title.TEXT)
+ element = session.ice_driver.find_element_by_id(
+ Constants.Home.Collaborate.ID)
+ element.location_once_scrolled_into_view
+ Wait.text_by_xpath(
+ Constants.Home.Collaborate.XPATH, Constants.Home.Collaborate.TEXT)
+ Wait.text_by_xpath(
+ Constants.Home.Validate.XPATH, Constants.Home.Validate.TEXT)
+ Wait.text_by_xpath(
+ Constants.Home.Incubate.XPATH, Constants.Home.Incubate.TEXT)
+ element = session.ice_driver.find_element_by_id(Constants.Home.Logo.ID)
+ element.location_once_scrolled_into_view
+ Wait.text_by_id(Constants.Home.Title.ID, Constants.Home.Title.TEXT)
+
+ @staticmethod
+ def go_to_signup_from_homepage():
+ Click.link_text(Constants.Home.GetStarted.LINK_TEXT)
+ Wait.text_by_css(
+ Constants.Signup.Title.CSS, Constants.Signup.Title.TEXT)
+
+ @staticmethod
+ def get_meta_order_of_element(element_id):
+ return Get.meta_order_by_id(element_id)
+
+ @staticmethod
+ def verify_num_of_existing_ids(requested_num_of_ids, id_prefix):
+ existing_id_objects_in_page = 0
+ ids = session.ice_driver.find_elements_by_xpath('//*[@id]')
+ for id in ids:
+ if id_prefix in id.get_attribute('id'):
+ # Print id.tag_name (id name as string).
+ logger.debug(id.get_attribute('id'))
+ existing_id_objects_in_page += 1
+ Helper.internal_assert(
+ existing_id_objects_in_page, requested_num_of_ids)
+ logger.debug("verify_num_of_existing_ids succeeded")
+
+ @staticmethod
+ def verify_existing_files_in_list(items_list, id_to_search_for):
+ element = session.ice_driver.find_elements_by_id(id_to_search_for)
+ element_attribute_items = json.loads(element[0].get_attribute('name'))
+ Helper.internal_assert(
+ len(items_list), len(element_attribute_items) - 1)
+ extracted_files_list = list()
+ for file in element_attribute_items:
+ extracted_files_list.append(file['File'])
+ for item in items_list:
+ if item not in extracted_files_list:
+ Helper.assertTrue(
+ False, "%s does not exist over the client's side" % item)
+ logger.debug(
+ "verify_existing_files_in_list succeeded, All vf repo files are available for choosing.")
diff --git a/services/frontend/fe_invite.py b/services/frontend/fe_invite.py
new file mode 100644
index 0000000..405581c
--- /dev/null
+++ b/services/frontend/fe_invite.py
@@ -0,0 +1,198 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from asyncio.tasks import wait
+
+from selenium.webdriver.support.select import Select
+
+from services.api.api_user import APIUser
+from services.api.api_virtual_function import APIVirtualFunction
+from services.constants import Constants, ServiceProvider
+from services.database.db_general import DBGeneral
+from services.database.db_user import DBUser
+from services.frontend.base_actions.click import Click
+from services.frontend.base_actions.enter import Enter
+from services.frontend.base_actions.get import Get
+from services.frontend.base_actions.wait import Wait
+from services.frontend.fe_general import FEGeneral
+from services.frontend.fe_user import FEUser
+from services.frontend.fe_wizard import FEWizard
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class FEInvite:
+
+ @staticmethod
+ def invite_users(user_content):
+ engName = user_content[0][
+ 'engagement_manual_id'] + ": " + user_content[0]['vfName']
+ vf_left_nav_id = "clickable-" + engName
+ Click.id(vf_left_nav_id)
+ FEWizard.invite_team_members_modal(user_content[1]['email'])
+ # self.sleep(1) # TODO need to wait until modal window is closed.
+ invitation_token = DBUser.select_invitation_token("invitation_token", "ice_invitation", "engagement_uuid",
+ user_content[0]['engagement_uuid'], user_content[1]['email'], 1)
+ inviterURL = Constants.Default.InviteURL.Login.TEXT + invitation_token
+ FEGeneral.re_open(inviterURL)
+ # Login with 2nd user #
+ title_id = "title-id-" + engName
+ FEUser.login(
+ user_content[1]['email'], Constants.Default.Password.TEXT, title_id)
+ Click.id(vf_left_nav_id)
+ actualVfName = Get.by_id(vf_left_nav_id)
+ Helper.internal_assert(engName, actualVfName)
+ Wait.text_by_id(Constants.Dashboard.Overview.Title.ID, engName)
+ FEUser.logout()
+ return vf_left_nav_id
+
+ @staticmethod
+ def invite_x_users(user_content, vf_left_nav_id, x):
+ for _ in range(x): # Invites 2-5
+ Click.id(vf_left_nav_id)
+ Click.id(Constants.Dashboard.LeftPanel.AddEngagement.ID)
+ FEWizard.add_vf()
+ Click.id(
+ Constants.Dashboard.Wizard.CloseButton.ID, wait_for_page=True)
+ FEWizard.invite_team_members_modal(user_content[1]['email'])
+ FEGeneral.refresh()
+
+ @staticmethod
+ def invite_and_validate_limit(user_content, vf_left_nav_id):
+ Click.id(Constants.Dashboard.LeftPanel.AddEngagement.ID)
+ FEWizard.add_vf()
+ Click.id(Constants.Dashboard.Wizard.CloseButton.ID, wait_for_page=True)
+ Click.id(vf_left_nav_id)
+ Click.id(Constants.Dashboard.Overview.TeamMember.ID)
+ Wait.text_by_css(Constants.Dashboard.Wizard.Title.CSS,
+ Constants.Dashboard.Wizard.InviteTeamMembers.Title.TEXT)
+ Enter.text_by_name("email", user_content[1]['email'])
+ Wait.text_by_css(Constants.SubmitButton.CSS,
+ Constants.Dashboard.Wizard.InviteTeamMembers.Button.TEXT)
+ Click.css(Constants.SubmitButton.CSS)
+ Wait.id(Constants.Toast.ID)
+ Helper.internal_assert(
+ Get.by_id(Constants.Toast.ID), "Invite couldn't be created")
+
+ @staticmethod
+ def invite_x_users_from_tm(list_of_invite_emails, countofUser, countOfem, num):
+ Enter.text_by_name(
+ "email", list_of_invite_emails[countofUser], wait_for_page=True)
+ for _ in range(num):
+ try:
+ session.run_negative(
+ lambda: Click.css("span.add-icon"), "css appears")
+ break
+ except: # button exists
+ pass
+ countofUser += 1
+# Click.css("span.add-icon")
+ Wait.xpath("//fieldset[" + str(countOfem) + "]/div/input")
+ Enter.text_by_xpath(
+ "//fieldset[" + str(countOfem) + "]/div/input", list_of_invite_emails[countofUser])
+ countOfem += 1
+ Click.css(Constants.SubmitButton.CSS, wait_for_page=True)
+
+ @staticmethod
+ def create_x_vfs(user_content, engName, x):
+ vflist = []
+ FEUser.login(user_content['email'], Constants.Default.Password.TEXT)
+ for _ in range(x):
+ vf_left_nav_id = "clickable-" + engName
+ Click.id(vf_left_nav_id)
+ Click.id(Constants.Dashboard.LeftPanel.AddEngagement.ID)
+ vfName = FEWizard.add_vf()
+ vflist.append(vfName)
+ Click.id(
+ Constants.Dashboard.Wizard.CloseButton.ID, wait_for_page=True)
+ return vflist
+
+ @staticmethod
+ def validations_for_user2(user_content, inviteEmail, vflist):
+ # Fetch one AT&T user ID.
+ engagement_id = DBGeneral.select_where(
+ "engagement_id", "ice_vf", "name", vflist[0], 1)
+ engagement_manual_id = DBGeneral.select_where(
+ "engagement_manual_id", "ice_engagement", "uuid", engagement_id, 1)
+ engLeadEmail = DBUser.select_el_email(vflist[0])
+ user_content['engagement_uuid'] = engagement_id
+ user_content['el_email'] = engLeadEmail
+ uuid = DBGeneral.select_where_email(
+ "uuid", "ice_user_profile", user_content['email'])
+ sponsor = ["AT&T", 'aaaaaa', inviteEmail, '3058000000']
+ invitation_token = DBUser.select_invitation_token(
+ "invitation_token", "ice_invitation", "engagement_uuid", engagement_id, inviteEmail, 1)
+ signUpURLforContact = DBUser.get_contact_signup_url(
+ invitation_token, uuid, sponsor[2], sponsor[1], sponsor[3], sponsor[0])
+ APIUser.signup_invited_user(
+ sponsor[0], inviteEmail, invitation_token, signUpURLforContact, user_content, True, wait_for_gitlab=False)
+ activationUrl2 = DBUser.get_activation_url(sponsor[2])
+ FEGeneral.re_open(activationUrl2) # Login with 2nd user #
+ engName = engagement_manual_id + ": " + vflist[0]
+ title_id = "clickable-" + engName
+ FEUser.login(inviteEmail, Constants.Default.Password.TEXT, title_id)
+ for vfName in vflist:
+ # Fetch one AT&T user ID.
+ engagement_id = DBGeneral.select_where(
+ "engagement_id", "ice_vf", "name", vfName, 1)
+ engagement_manual_id = DBGeneral.select_where(
+ "engagement_manual_id", "ice_engagement", "uuid", engagement_id, 1)
+ engName = engagement_manual_id + ": " + vfName
+ vf_left_nav_id = "clickable-" + engName
+ Click.id(vf_left_nav_id, wait_for_page=True)
+
+ @staticmethod
+ def invite_x_users_and_verify_VF_appers_for_invited(user_content, engName):
+ inviteEmail = Helper.rand_string('randomString') + "@intl." + ServiceProvider.email
+ vflist = FEInvite.create_x_vfs(user_content, engName, x=3)
+ for vfName in vflist:
+ # Fetch one AT&T user ID.
+ engagement_id = DBGeneral.select_where(
+ "engagement_id", "ice_vf", "name", vfName, 1)
+ engagement_manual_id = DBGeneral.select_where(
+ "engagement_manual_id", "ice_engagement", "uuid", engagement_id, 1)
+ engName = engagement_manual_id + ": " + vfName
+ vf_left_nav_id = "clickable-" + engName
+ Click.id(vf_left_nav_id)
+ FEWizard.invite_team_members_modal(inviteEmail)
+ FEGeneral.refresh()
+ # validations
+ FEInvite.validations_for_user2(user_content, inviteEmail, vflist)
diff --git a/services/frontend/fe_next_step.py b/services/frontend/fe_next_step.py
new file mode 100644
index 0000000..be59949
--- /dev/null
+++ b/services/frontend/fe_next_step.py
@@ -0,0 +1,56 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+'''
+Created on 20 Jul 2017
+'''
+from services.constants import Constants
+from services.frontend.base_actions.click import Click
+from services.frontend.base_actions.wait import Wait
+
+
+class FENextStep(object):
+
+ @staticmethod
+ def check_select_deselect_all_files():
+ Click.id(Constants.Dashboard.Overview.NextSteps.Add.AssociatedFiles.ID)
+ Click.link_text(
+ Constants.Dashboard.Overview.NextSteps.Add.AssociatedFiles.SELECT_ALL_FILES_NAME)
+ Wait.text_by_id(
+ Constants.Dashboard.Overview.NextSteps.Add.AssociatedFiles.ID,
+ Constants.Dashboard.Overview.NextSteps.Add.AssociatedFiles.ALL_FILES_SELECTED)
diff --git a/services/frontend/fe_overview.py b/services/frontend/fe_overview.py
new file mode 100644
index 0000000..8d05f0c
--- /dev/null
+++ b/services/frontend/fe_overview.py
@@ -0,0 +1,427 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import datetime
+
+from django.utils import timezone
+from selenium.webdriver.support.select import Select
+
+from services.constants import Constants
+from services.database.db_general import DBGeneral
+from services.database.db_user import DBUser
+from services.database.db_virtual_function import DBVirtualFunction
+from services.frontend.base_actions.click import Click
+from services.frontend.base_actions.enter import Enter
+from services.frontend.base_actions.get import Get
+from services.frontend.base_actions.wait import Wait
+from services.frontend.fe_general import FEGeneral
+from services.frontend.fe_user import FEUser
+from services.frontend.fe_wizard import FEWizard
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+logger = LoggingServiceFactory.get_logger()
+
+class FEOverview:
+
+ @staticmethod
+ def click_on_vf(user_content):
+ vfFullName = user_content[
+ 'engagement_manual_id'] + ": " + user_content['vfName']
+ Enter.text_by_id(Constants.Dashboard.LeftPanel.SearchBox.ID, user_content[
+ 'vfName'])
+ Click.id(Constants.Dashboard.LeftPanel.SearchBox.Results.ID %
+ user_content['vfName'])
+ Wait.text_by_id(
+ Constants.Dashboard.Overview.Title.ID, vfFullName)
+
+ @staticmethod
+ def go_to_eng_overview_by_clicking_on_the_created_NS(user_content):
+ logger.debug(
+ "Go to engagement's overview by clicking on the created Next Step")
+ Click.name(user_content['engagement_manual_id'], wait_for_page=True)
+ Wait.text_by_id(
+ Constants.Dashboard.Overview.Title.ID, user_content['engagement_manual_id'] + ":", wait_for_page=True)
+ FEGeneral.re_open(Constants.Default.LoginURL.TEXT)
+ logger.debug("Login with EL user " + user_content['el_email'])
+ FEUser.login(user_content['el_email'], Constants.Default.Password.TEXT)
+ # Query to select all assigned next steps on TODO state #
+ el_native_id = str(DBGeneral.select_where(
+ "id", "ice_user_profile", "email", user_content['el_email'], 1))
+ queryStr = "SELECT count(*) FROM ice_user_profile AS users, ice_next_step_assignees AS assignees, ice_next_step AS ns WHERE users.id=" + \
+ el_native_id + \
+ " AND users.id=assignees.iceuserprofile_id AND assignees.nextstep_id=ns.uuid AND ns.state='Incomplete';"
+ el_assigned_ns = str(DBGeneral.select_query(queryStr))
+ logger.debug("el_assigned_ns=" + el_assigned_ns)
+ Wait.page_has_loaded()
+ if (int(el_assigned_ns) >= 5):
+ logger.debug(
+ "EL has 5 or more assigned next steps, checking that only 5 are shown")
+ ns_list = Get.by_id("next-steps-list")
+ if (ns_list.count("Engagement - ") > 5):
+ logger.error("More than 5 next steps are listed in dashboard.")
+ raise
+
+ @staticmethod
+ def complete_defaults_nextsteps(engagement_id):
+ # NEXT STEP ID
+ next_steps = DBVirtualFunction.select_next_steps_uuids_by_stage(
+ engagement_id, Constants.EngagementStages.INTAKE)
+ for next_step in next_steps:
+ Wait.id(next_step)
+ Click.id(next_step, wait_for_page=True)
+
+ @staticmethod
+ def check_stage_notifications(stage):
+ activityLogID = "activity-log-0"
+ activityLogMsg = "Engagement stage is now %s" % stage
+ uiActivityLog = Get.by_id(activityLogID)
+ if activityLogMsg not in uiActivityLog:
+ return False
+ return True
+
+ @staticmethod
+ def check_stage_next_steps(stage, engagement_uuid):
+ ns_list = DBGeneral.select_where_and("description", "ice_next_step",
+ "engagement_id", engagement_uuid,
+ "engagement_stage", stage, 0) # List of next steps from DB.
+ logger.debug("Got list of Next Steps for current stage " + stage)
+ for i in range(len(ns_list)):
+ ns_description = ns_list[i] # Value number i from the list.
+ ns_uuid = DBGeneral.select_where_and("uuid", "ice_next_step",
+ "engagement_id", engagement_uuid,
+ "description", ns_description, 1)
+ logger.debug(
+ "Compare presented text of next step with the text from DB.")
+ portal_ns = Get.by_id("step-" + ns_uuid)
+ # Get from UI the text of relevant next step.
+ if ns_description not in portal_ns:
+ logger.error("Next step wasn't found in stage " + stage)
+ raise
+
+ @staticmethod
+ def change_engagement_stage(next_stage, is_negative=False):
+ # Click on next stage.
+ Click.id(Constants.Dashboard.Overview.Stage.Set.ID + next_stage)
+ txtLine2ID = "modal-message-" + next_stage
+ if is_negative:
+ session.run_negative(
+ lambda: Wait.id(txtLine2ID), "Error: modal window opened.")
+ else:
+ Wait.text_by_id(
+ txtLine2ID, "Are you sure you want to set the Engagement's stage to " + next_stage + "?")
+ # Click on Approve (after validations inside window).
+ Click.xpath(
+ Constants.Dashboard.Overview.Stage.Approve.XPATH, wait_for_page=True)
+
+ @staticmethod
+ def check_progress(expected_progress):
+ currentProgress = Get.by_id(
+ Constants.Dashboard.Overview.Progress.Percent.ID)
+ Helper.internal_assert(currentProgress, expected_progress)
+
+ @staticmethod
+ def check_vnf_version(expected_progress):
+ current_vnf_value = Get.by_css(
+ "." + Constants.Dashboard.Overview.Progress.VnfVersion.CLASS)
+ Helper.internal_assert(current_vnf_value, expected_progress)
+
+ @staticmethod
+ def set_progress(new_value):
+ Click.id(Constants.Dashboard.Overview.Progress.Change.ID)
+ Helper.internal_assert(Constants.Dashboard.Overview.Progress.Wizard.Title.TEXT,
+ Get.by_id(Constants.Dashboard.Modal.TITLE_ID))
+ Enter.text_by_name(
+ Constants.Dashboard.Overview.Progress.Wizard.NAME, new_value)
+ Wait.text_by_css(Constants.SubmitButton.CSS,
+ Constants.Dashboard.Overview.Progress.Wizard.Button.TEXT)
+ Click.css(Constants.SubmitButton.CSS)
+ Wait.modal_to_dissappear()
+
+ @staticmethod
+ def delete_next_step(next_step_uuid):
+ Click.id("step-" + next_step_uuid, wait_for_page=True)
+ Click.id("delete-" + next_step_uuid, wait_for_page=True)
+ Wait.text_by_id(
+ Constants.Dashboard.GeneralPrompt.Title.ID, "Delete Step")
+ Click.id(
+ Constants.Dashboard.GeneralPrompt.ApproveButton.ID, wait_for_page=True)
+ Wait.id_to_dissappear("test_" + next_step_uuid)
+
+ @staticmethod
+ def click_on_admin_dropdown():
+ Click.id(
+ Constants.Dashboard.Overview.AdminDropdown.ID, wait_for_page=True)
+
+ @staticmethod
+ def click_on_archeive_engagement_from_dropdown():
+ FEOverview.click_on_admin_dropdown()
+ Click.link_text(
+ Constants.Dashboard.Overview.AdminDropdown.ArchiveEngagement.LINK_TEXT, wait_for_page=True)
+
+ @staticmethod
+ def archive_engagement_modal(engagement_manual_id, vf_name):
+ Wait.text_by_id(Constants.Dashboard.Overview.AdminDropdown.ArchiveEngagement.Wizard.Title.ID,
+ Constants.Dashboard.Overview.AdminDropdown.ArchiveEngagement.Wizard.Title.TEXT)
+ random_reason = Helper.rand_string()
+ Enter.text_by_name(Constants.Dashboard.Overview.AdminDropdown.ArchiveEngagement.Wizard.Reason.NAME,
+ random_reason)
+ Click.id(Constants.SubmitButton.ID)
+ Wait.text_by_id(Constants.Toast.ID, "Engagement '%s: %s' archived successfully." %
+ (engagement_manual_id, vf_name))
+ query = "select archived_time,archive_reason from ice_engagement where engagement_manual_id='{engagement_manual_id}'".format(
+ engagement_manual_id=engagement_manual_id)
+ archived_time, db_reason = DBGeneral.select_query(query, "list")
+ Helper.assertTrue(archived_time != None)
+ Helper.internal_assert(random_reason, db_reason)
+
+ @staticmethod
+ def click_on_change_reviewer_from_dropdown():
+ FEOverview.click_on_admin_dropdown()
+ Click.link_text(
+ Constants.Dashboard.Overview.AdminDropdown.ChangeReviewer.LINK_TEXT)
+
+ @staticmethod
+ def select_engagement_lead_from_list(el_name):
+ Wait.name(
+ Constants.Dashboard.Overview.AdminDropdown.ChangeReviewer.Wizard.Select.NAME, wait_for_page=True)
+ Select(session.ice_driver.find_element_by_name(
+ Constants.Dashboard.Overview.AdminDropdown.ChangeReviewer.Wizard.Select.NAME)).select_by_visible_text(el_name)
+
+ @staticmethod
+ def change_engagement_lead_modal(el_name, is_reviewer=True):
+ Wait.text_by_id(Constants.Dashboard.Overview.AdminDropdown.ChangeReviewer.Wizard.Title.ID,
+ Constants.Dashboard.Overview.AdminDropdown.ChangeReviewer.Wizard.Title.TEXT)
+ FEOverview.select_engagement_lead_from_list(el_name)
+ if is_reviewer:
+ Wait.text_by_id(
+ Constants.Toast.ID, Constants.Dashboard.Overview.AdminDropdown.ChangeReviewer.Toast.TEXT)
+ else:
+ Wait.text_by_id(
+ Constants.Toast.ID, Constants.Dashboard.Overview.AdminDropdown.ChangePeerReviewer.Toast.TEXT)
+
+ @staticmethod
+ def click_on_change_peer_reviewer_from_dropdown():
+ FEOverview.click_on_admin_dropdown()
+ Click.link_text(
+ Constants.Dashboard.Overview.AdminDropdown.ChangePeerReviewer.LINK_TEXT)
+ Wait.text_by_id(Constants.Dashboard.Overview.AdminDropdown.ChangePeerReviewer.Wizard.Title.ID,
+ Constants.Dashboard.Overview.AdminDropdown.ChangePeerReviewer.Wizard.Title.TEXT)
+
+ @staticmethod
+ def click_on_update_status_from_dropdown():
+ FEOverview.click_on_admin_dropdown()
+ Click.link_text(
+ Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.LINK_TEXT)
+ Wait.text_by_id("update-engagement-status-title", "Update Status")
+
+ @staticmethod
+ def fill_update_status_form_admin_dropdown():
+ random_string = Helper.rand_string()
+ Enter.text_by_name(
+ Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.PROGRESS, str(50))
+ Enter.date_picker(Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.PROGRESS_CSS,
+ Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.TARGET)
+ Enter.date_picker(Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.PROGRESS_CSS,
+ Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.HEAT)
+ Enter.date_picker(Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.PROGRESS_CSS,
+ Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.IMAGE_SACN)
+ Enter.date_picker(Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.PROGRESS_CSS,
+ Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.AIC)
+ Enter.date_picker(Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.PROGRESS_CSS,
+ Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.ASDC)
+ Enter.text_by_name(
+ Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.STATUS, random_string)
+ Click.css(
+ Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.SUBMIT, wait_for_page=True)
+ Wait.text_by_id(
+ Constants.Toast.ID, Constants.Dashboard.Overview.AdminDropdown.UpdateStatus.SUCCESS_MSG, wait_for_page=True)
+ Wait.text_by_id(
+ Constants.Dashboard.Overview.Status.Description.ID, random_string)
+
+ @staticmethod
+ def get_next_step_description(idx):
+ return str(Get.by_id("step-description-%s" % idx, wait_for_page=True))
+
+ @staticmethod
+ def get_list_of_next_steps():
+ i = 0
+ ns_list = []
+ steps_length = len(
+ session.ice_driver.find_elements_by_css_selector(".step-indication > li"))
+ while i < steps_length:
+ ns_list.append(FEOverview.get_next_step_description(i))
+ i += 1
+ return ns_list
+
+ @staticmethod
+ def validate_next_steps_order(steps_uuids):
+ ui_steps = FEOverview.get_list_of_next_steps()
+ for idx, step_uuid in enumerate(steps_uuids):
+ db_step_text = DBVirtualFunction.select_next_step_description(
+ step_uuid)
+ Wait.text_by_id(Constants.Dashboard.Overview.NextSteps.Add.Description.STEP_DESC_ID +
+ str(idx), ui_steps[idx], wait_for_page=True)
+ if db_step_text != ui_steps[idx]:
+ raise AssertionError("Next step is not located in expected index. db_step_text = "
+ + db_step_text + " ui_steps[idx] = " + ui_steps[idx] + "|| uuid = " + step_uuid)
+
+ @staticmethod
+ def next_steps_filter_by_files():
+ Click.id(
+ Constants.Dashboard.Overview.NextSteps.FilterByFileDropDown.ID)
+ Click.link_text(
+ Constants.Dashboard.Overview.NextSteps.FilterByFileDropDown.ANY_FILE_LINK_TEXT)
+ Click.link_text(
+ Constants.Dashboard.Overview.NextSteps.FilterByFileDropDown.FILE0_LINK_TEXT)
+ Click.id(
+ Constants.Dashboard.Overview.NextSteps.FilterByFileDropDown.ID)
+
+ @staticmethod
+ def complete_next_step(step_uuid):
+ Click.id(step_uuid)
+
+ @staticmethod
+ def complete_next_step_and_wait_for_it_to_disappear(step_uuid):
+ Click.id(step_uuid)
+ Wait.id_to_dissappear(step_uuid)
+
+ @staticmethod
+ def next_steps_filter_by_states():
+ Click.id(Constants.Dashboard.Overview.NextSteps.StateDropDown.ID)
+ Click.link_text(
+ Constants.Dashboard.Overview.NextSteps.StateDropDown.INCOMPLETE_LINK_TEXT)
+ Click.link_text(
+ Constants.Dashboard.Overview.NextSteps.StateDropDown.COMPLETED_LINK_TEXT)
+ Click.id(Constants.Dashboard.Overview.NextSteps.StateDropDown.ID)
+
+ @staticmethod
+ def add_next_step():
+ Click.id(Constants.Dashboard.Overview.NextSteps.Add.ID)
+ Wait.text_by_css(Constants.Dashboard.Overview.NextSteps.Add.Title.CSS,
+ Constants.Dashboard.Overview.NextSteps.Add.Title.TEXT)
+ ns_description = "New next step - " + \
+ Helper.rand_string("randomString")
+ Click.id(Constants.Dashboard.Overview.NextSteps.Add.Description.ID)
+ Enter.text_by_id(
+ Constants.Dashboard.Overview.NextSteps.Add.Description.ID, ns_description)
+ FEWizard.date_picker_add_ns(0)
+ Wait.text_by_css(Constants.SubmitButton.CSS,
+ Constants.Dashboard.Overview.NextSteps.Add.Button.TEXT)
+ Click.css(Constants.SubmitButton.CSS)
+ Wait.modal_to_dissappear()
+
+ @staticmethod
+ def click_on_team_member(full_name):
+ Click.id(Constants.Dashboard.Overview.TeamMember.MEMBER_ID % full_name)
+ Wait.id(Constants.Dashboard.Overview.TeamMember.Title.ID)
+
+ @staticmethod
+ def remove_user_from_eng_team(full_name, is_negative=False):
+ FEOverview.click_on_team_member(full_name)
+ if is_negative:
+ Wait.id_to_dissappear(
+ Constants.Dashboard.Overview.TeamMember.RemoveUser.ID)
+ else:
+ Click.id(Constants.Dashboard.Overview.TeamMember.RemoveUser.ID)
+ Wait.text_by_id(Constants.Dashboard.GeneralPrompt.UpperTitle.ID,
+ Constants.Dashboard.Overview.TeamMember.RemoveUser.Title.TEXT % full_name)
+ Wait.text_by_id(Constants.Dashboard.GeneralPrompt.Title.ID,
+ Constants.Dashboard.Overview.TeamMember.RemoveUser.Message.TEXT)
+ Click.id(Constants.Dashboard.GeneralPrompt.ApproveButton.ID)
+ FEGeneral.refresh()
+ Wait.id_to_dissappear(
+ Constants.Dashboard.Overview.TeamMember.MEMBER_ID % full_name)
+
+ @staticmethod
+ def invite_and_reopen_link(user_content, other_el_email):
+ enguuid = DBGeneral.select_where(
+ "uuid", "ice_engagement", "engagement_manual_id", user_content['engagement_manual_id'], 1)
+ invitation_token = DBUser.select_invitation_token(
+ "invitation_token", "ice_invitation", "engagement_uuid", enguuid, other_el_email, 1)
+ inviterURL = Constants.Default.InviteURL.Login.TEXT + invitation_token
+ FEGeneral.re_open(inviterURL)
+
+ @staticmethod
+ def create_and_verify_VF_with_VFversion():
+ Click.id(
+ Constants.Dashboard.LeftPanel.AddEngagement.ID, wait_for_page=True)
+ vfName = FEWizard.add_vf()
+ version_name = DBVirtualFunction.select_vf_version_by_vf_name(vfName)
+ vfNameDb = DBVirtualFunction.select_vf_name_by_vf_version(version_name)
+ Helper.internal_assert(vfNameDb, vfName)
+
+ @staticmethod
+ def validate_empty_associated_files():
+ FEOverview.add_next_step()
+ Click.id(Constants.Dashboard.Overview.NextSteps.AssociatedFiles.ID)
+ Wait.text_by_id(Constants.Dashboard.Overview.NextSteps.AssociatedFiles.EmptyMsgID,
+ Constants.Dashboard.Overview.NextSteps.AssociatedFiles.EmptyMsg)
+
+ @staticmethod
+ def validate_associated_files(file_name):
+ Click.id(Constants.Dashboard.Overview.NextSteps.AssociatedFiles.ID)
+ Wait.text_by_id(
+ Constants.Dashboard.Overview.NextSteps.AssociatedFiles.FileId, file_name)
+
+ @staticmethod
+ def validate_bucket_url(eng_manual_id, vf_name):
+ expected_text = Constants.Dashboard.Overview.BucketURL.TEXT + \
+ eng_manual_id + "_" + vf_name.lower()
+ Wait.text_by_id(
+ Constants.Dashboard.Overview.BucketURL.ID, expected_text, True)
+
+ @staticmethod
+ def verify_validation_dates():
+ validation_date = Get.by_id(
+ Constants.Dashboard.Overview.Progress.ValidationsDates.AIC_ID, True)
+ validation_date = datetime.datetime.strptime(
+ validation_date, "%m/%d/%y").date()
+ current_date = timezone.now().date()
+ Helper.internal_assert(validation_date, current_date)
+
+ @staticmethod
+ def open_add_next_step_modal_from_overview():
+ Click.id(Constants.Dashboard.Overview.NextSteps.Add.ID,
+ wait_for_page=True)
+ Wait.text_by_css(Constants.Dashboard.Checklist.AddNS.CSS,
+ Constants.Dashboard.Overview.NextSteps.Add.TITLE)
+ Helper.internal_assert(
+ Constants.Dashboard.Checklist.AddNS.TITLE,
+ Get.by_css(Constants.FEGeneral.CSS.H2))
diff --git a/services/frontend/fe_user.py b/services/frontend/fe_user.py
new file mode 100644
index 0000000..91cf7eb
--- /dev/null
+++ b/services/frontend/fe_user.py
@@ -0,0 +1,403 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from selenium.webdriver.support.select import Select
+
+from services.api.api_user import APIUser
+from services.api.api_virtual_function import APIVirtualFunction
+from services.constants import Constants
+from services.database.db_general import DBGeneral
+from services.database.db_user import DBUser
+from services.frontend.base_actions.click import Click
+from services.frontend.base_actions.enter import Enter
+from services.frontend.base_actions.get import Get
+from services.frontend.base_actions.wait import Wait
+from services.frontend.fe_general import FEGeneral
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class FEUser:
+
+ @staticmethod
+ def login(email, password, expected_element=Constants.Dashboard.Statuses.Title.ID, element_type="id"):
+ try:
+ logger.debug("Verifying and Insert Login page elements:")
+ logger.debug("Insert Email " + email)
+ Wait.name(Constants.Login.Email.NAME, wait_for_page=True)
+ Enter.text_by_name(Constants.Login.Email.NAME, email)
+ logger.debug("Insert Password")
+ Enter.text_by_name(Constants.Login.Password.NAME, password)
+ logger.debug("Click Login Button")
+ Click.css(Constants.SubmitButton.CSS)
+ logger.debug("Login Button clicked")
+ if element_type == 'id':
+ Wait.id(expected_element, True)
+ elif element_type == 'css':
+ Wait.css(expected_element, True)
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Login FAILED: email=%s password=%s" % (email, password)
+ logger.error(errorMsg)
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def relogin(email, password, expected_element=Constants.Dashboard.Statuses.Title.ID, element_type="id"):
+ FEGeneral.re_open(Constants.Default.LoginURL.TEXT)
+ FEUser.login(email, password, expected_element, element_type)
+
+ @staticmethod
+ def logout():
+ Click.id(Constants.Dashboard.Avatar.ID)
+ Click.link_text(Constants.Dashboard.Avatar.Logout.LINK_TEXT)
+
+ @staticmethod
+ def activate_and_login(email, password, expected_element=Constants.Dashboard.Statuses.Title.ID, element_type="id"):
+ activationUrl = DBUser.get_activation_url(email)
+ FEGeneral.re_open(activationUrl)
+ FEUser.login(email, password, expected_element, element_type)
+
+ @staticmethod
+ def open_account_form():
+ Click.id(Constants.Dashboard.Avatar.ID, wait_for_page=True)
+ Click.link_text(
+ Constants.Dashboard.Avatar.Account.LINK_TEXT, wait_for_page=True)
+
+ @staticmethod
+ # Update account API - only adds new SSH key!
+ def update_account_and_return_changes():
+ try:
+ Select(session.ice_driver.find_element_by_name(
+ "company")).select_by_visible_text("Nokia")
+ randomName = Helper.rand_string("randomString")
+ Enter.text_by_name("fullname", randomName)
+ phone = "97258" + Helper.rand_string("randomNumber", 6)
+ Enter.text_by_name("phone", phone)
+ password = Constants.Default.Password.NewPass.TEXT
+ Enter.text_by_name("password", password)
+ Enter.text_by_name("confirm_password", password)
+ Wait.text_by_css("button.btn.btn-primary", "Update")
+ Click.css("button.btn.btn-primary")
+ Wait.text_by_id(
+ Constants.Toast.ID, "Account was updated successfully!")
+ Click.id(Constants.Dashboard.Statuses.ID)
+
+ accountObj = [randomName, phone, password]
+ return accountObj
+ # If failed - count the failure and add the error to list of errors.
+ except:
+ errorMsg = "Failed in update accaunt ."
+ raise Exception(errorMsg)
+ raise
+
+ @staticmethod
+ def go_to_account():
+ try:
+ FEUser.click_on_avatar()
+ FEUser.click_on_account()
+ except Exception as e:
+ errorMsg = "Failed to go to Account page."
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def go_to_notifications():
+ try:
+ FEUser.click_on_avatar()
+ FEUser.click_on_notifications()
+ Wait.page_has_loaded()
+ except Exception as e:
+ errorMsg = "Failed to go to Notifications page."
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def click_on_avatar():
+ try:
+ Click.id(Constants.Dashboard.Avatar.ID, wait_for_page=True)
+ except Exception as e:
+ errorMsg = "Failed to click_on on Avatar."
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def click_on_admin():
+ try:
+ Click.id(
+ Constants.Dashboard.Avatar.Admin.Title.ID, wait_for_page=True)
+ except Exception as e:
+ errorMsg = "Failed to click_on on Admin."
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def click_on_feedback():
+ Click.id(Constants.Dashboard.Feedback.ID, wait_for_page=True)
+ Wait.id(
+ Constants.Dashboard.Feedback.FeedbackModal.SAVE_BTN_ID, wait_for_page=True)
+
+ @staticmethod
+ def validate_feedback(description, user_email):
+ query = "SELECT user_id FROM ice_feedback where description = '{desc}'".format(
+ desc=description)
+ feedback_user_uuid = DBGeneral.select_query(query)
+ query = "SELECT id FROM ice_user_profile where email = '{email}'".format(
+ email=user_email)
+ user_uuid = DBGeneral.select_query(query)
+ Helper.internal_assert(user_uuid, feedback_user_uuid)
+
+ @staticmethod
+ def add_feedback():
+ Wait.css("textarea[name=\"description\"]", wait_for_page=True)
+ description = Helper.rand_string("randomString")
+ Enter.text_by_css("textarea[name=\"description\"]", description)
+ Click.id(
+ Constants.Dashboard.Feedback.FeedbackModal.SAVE_BTN_ID, wait_for_page=True)
+ Wait.text_by_id(Constants.Toast.ID,
+ "Feedback was sent successfully.", wait_for_page=True)
+ return description
+
+ @staticmethod
+ def click_on_account():
+ try:
+ Click.link_text(Constants.Dashboard.Avatar.Account.LINK_TEXT)
+ Wait.text_by_css(Constants.Dashboard.Avatar.Account.Title.CSS,
+ Constants.Dashboard.Avatar.Account.Title.TEXT)
+ except Exception as e:
+ errorMsg = "Failed to click_on on Admin."
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def click_on_notifications():
+ try:
+ Click.link_text(
+ Constants.Dashboard.Avatar.Notifications.LINK_TEXT, wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.Avatar.Notifications.Title.ID,
+ Constants.Dashboard.Avatar.Notifications.Title.TEXT, wait_for_page=True)
+ except Exception as e:
+ errorMsg = "Failed to click_on on Admin."
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def go_to_admin():
+ try:
+ FEUser.click_on_avatar()
+ FEUser.click_on_admin()
+ except Exception as e:
+ errorMsg = "Failed to go to Admin page."
+ raise Exception(errorMsg, e)
+
+ @staticmethod
+ def assigned_one_NS_to_user(user_content):
+ nextStepsNumber = int(
+ Get.by_id("next-steps-header").split('(')[1][:-1])
+ if (nextStepsNumber != 0):
+ logger.error("assigned ns: " + str(nextStepsNumber))
+ logger.error(
+ "APIUser should not have assigned next steps at first login.")
+ raise
+ if (Get.by_id("next-steps-list") != "No next steps are assigned to you."):
+ logger.error(
+ "No assigned next steps and text 'No next steps are assigned to you.' was not found.")
+ raise
+ token = "token " + APIUser.login_user(user_content['el_email'])
+ user_content['session_token'] = token
+ logger.debug(
+ "Adding new next step (via api) and assigning it to user " + user_content['full_name'])
+ APIVirtualFunction.add_next_step(user_content)
+ logger.debug(
+ "Refresh page and look for changes in assigned next steps section:")
+ FEGeneral.refresh()
+ logger.debug(" > Check if number has changed in 'Assigned To You'")
+ Wait.text_by_id(
+ "next-steps-header", "Assigned To You (1)", wait_for_page=True)
+
+ @staticmethod
+ def set_ssh_key_from_account(key, is_negative=False):
+ FEUser.go_to_account()
+ Enter.text_by_name(Constants.Dashboard.Avatar.Account.SSHKey.NAME, key)
+ Click.css(Constants.SubmitButton.CSS)
+ if is_negative:
+ Wait.text_by_id(
+ Constants.Toast.ID, Constants.Dashboard.Avatar.Account.SSHKey.UpdateFailed.TEXT)
+ else:
+ Wait.text_by_id(
+ Constants.Toast.ID, Constants.Dashboard.Avatar.Account.Update.Success.TEXT)
+
+ @staticmethod
+ def reset_password():
+ Wait.text_by_css(
+ Constants.UpdatePassword.Title.CSS, Constants.UpdatePassword.Title.TEXT)
+ Wait.text_by_css(
+ Constants.UpdatePassword.SubTitle.CSS, Constants.UpdatePassword.SubTitle.TEXT)
+ Wait.text_by_css(
+ Constants.SubmitButton.CSS, Constants.UpdatePassword.Button.TEXT)
+ Enter.text_by_name(
+ Constants.UpdatePassword.Password.NAME, Constants.Default.Password.NewPass.TEXT)
+ Enter.text_by_name(
+ Constants.UpdatePassword.ConfirmPassword.NAME, Constants.Default.Password.NewPass.TEXT)
+ Click.css(Constants.SubmitButton.CSS)
+ Wait.text_by_id(
+ Constants.Toast.ID, Constants.UpdatePassword.Toast.TEXT)
+
+ @staticmethod
+ def delete_notification(notificationID):
+ if isinstance(notificationID, tuple):
+ notificationID = notificationID[0]
+ delete_button = Constants.Dashboard.Avatar.Notifications.DeleteNotification.ID + \
+ notificationID
+ # Click on delete button.
+ Click.id(delete_button, wait_for_page=True)
+ Wait.id_to_dissappear(delete_button)
+
+ @staticmethod
+ def validate_notifications(notificationIDs, notification_list):
+ ui_list = []
+ for notifID in notificationIDs:
+ if isinstance(notifID, tuple):
+ notifID = notifID[0]
+ ui_list.append(str(Get.by_id(
+ Constants.Dashboard.Avatar.Notifications.NotificationColumn.ID + notifID)))
+ for activity in notification_list:
+ if not any(activity in s for s in ui_list):
+ raise AssertionError(
+ "Activity: \"" + activity + "\" not appears in UI")
+
+ @staticmethod
+ def click_on_export_excel(user_content):
+ Enter.text_by_id(
+ Constants.Dashboard.Statuses.SearchBox.ID, user_content['vfName'])
+ engName = user_content[
+ 'engagement_manual_id'] + ": " + user_content['vfName']
+ engSearchID = "eng-" + engName
+ Wait.id(engSearchID)
+ # Find the download link and click it
+ Click.id(Constants.Dashboard.Statuses.ExportExcel.ID)
+
+ @staticmethod
+ def open_invite_team_member_form(vf_left_nav_id):
+ Click.id(vf_left_nav_id)
+ Click.id(Constants.Dashboard.Overview.TeamMember.ID)
+ Wait.text_by_name(Constants.Dashboard.Wizard.InviteTeamMembers.Title.NAME,
+ Constants.Dashboard.Wizard.InviteTeamMembers.Title.TEXT)
+
+ @staticmethod
+ def invite_single_user_to_team(email):
+ Enter.text_by_name("email", email, wait_for_page=True)
+ Click.css(Constants.SubmitButton.CSS, wait_for_page=True)
+
+ @staticmethod
+ def go_to_user_profile_settings():
+ FEUser.go_to_account()
+ Click.id(
+ Constants.Dashboard.Avatar.Account.UserProfileSettings.ID, wait_for_page=True)
+ Wait.text_by_id(Constants.Dashboard.Avatar.Account.UserProfileSettings.TitleID,
+ Constants.Dashboard.Avatar.Account.UserProfileSettings.TitleText, wait_for_page=True)
+
+ @staticmethod
+ def check_user_profile_settings_checkboxes():
+ Click.id(
+ Constants.Dashboard.Avatar.Account.UserProfileSettings.ReceiveEmailsID, wait_for_page=True)
+ Click.id(
+ Constants.Dashboard.Avatar.Account.UserProfileSettings.ReceiveEmailEveryTimeID, wait_for_page=True)
+ Click.id(
+ Constants.Dashboard.Avatar.Account.UserProfileSettings.ReceiveDigestEmailID, wait_for_page=True)
+ Click.id(
+ Constants.Dashboard.Avatar.Account.UserProfileSettings.UpdateButtonID, wait_for_page=True)
+
+ @staticmethod
+ def validate_user_profile_settings_checkboxes(checked):
+ Wait.page_has_loaded()
+ receive_emails = Get.is_selected_by_id(
+ Constants.Dashboard.Avatar.Account.UserProfileSettings.ReceiveEmailsID, wait_for_page=True)
+ Helper.internal_assert(receive_emails, checked)
+ receive_notifications = \
+ Get.is_selected_by_id(
+ Constants.Dashboard.Avatar.Account.UserProfileSettings.ReceiveNotificationsID)
+ receive_email_every_time = \
+ Get.is_selected_by_id(
+ Constants.Dashboard.Avatar.Account.UserProfileSettings.ReceiveEmailEveryTimeID)
+ Helper.internal_assert(receive_email_every_time, checked)
+ receive_digest_email = \
+ Get.is_selected_by_id(
+ Constants.Dashboard.Avatar.Account.UserProfileSettings.ReceiveDigestEmailID, wait_for_page=True)
+ Helper.internal_assert(receive_digest_email, not checked)
+
+ @staticmethod
+ def compare_notifications_count_for_user(expected_count):
+ Wait.text_by_id(
+ Constants.Dashboard.Avatar.Notifications.Count.ID, expected_count, wait_for_page=True)
+
+ @staticmethod
+ def check_notification_number_is_not_presented():
+ FEGeneral.refresh()
+ Wait.id_to_dissappear(
+ Constants.Dashboard.Avatar.Notifications.Count.ID, wait_for_page=True)
+
+ @staticmethod
+ def validate_account_details(full_name, phone_number, ssh_key):
+ Helper.internal_assert(full_name, Get.value_by_name(
+ Constants.Dashboard.Avatar.Account.FullName.NAME))
+ Helper.internal_assert(phone_number, Get.value_by_name(
+ Constants.Dashboard.Avatar.Account.Phone.NAME))
+ Helper.internal_assert(
+ ssh_key, Get.value_by_name(Constants.Dashboard.Avatar.Account.SSHKey.NAME))
+
+ @staticmethod
+ def check_rgwa_access_key(my_key):
+ Wait.text_by_id(
+ Constants.Dashboard.Avatar.Account.RGWA.Key.KEY_ID, my_key)
+
+ @staticmethod
+ def check_rgwa_access_secret(my_secret):
+ Click.id(Constants.Dashboard.Avatar.Account.RGWA.Secret.BUTTON_ID)
+ Wait.text_by_id(
+ Constants.Dashboard.Avatar.Account.RGWA.Secret.SECRET_ID, my_secret)
+
+ @staticmethod
+ def get_rgwa_access_secret():
+ Click.id(Constants.Dashboard.Avatar.Account.RGWA.Secret.BUTTON_ID,
+ wait_for_page=True)
+ secret = Get.by_id(
+ Constants.Dashboard.Avatar.Account.RGWA.Secret.SECRET_ID, wait_for_page=True)
+ return secret
+
+ @staticmethod
+ def check_rgwa_access_secret_not_presented():
+ Wait.text_by_id(
+ Constants.Dashboard.Avatar.Account.RGWA.Secret.SECRET_ID,
+ Constants.Dashboard.Avatar.Account.RGWA.Secret.SECRET_TEXT)
diff --git a/services/frontend/fe_wizard.py b/services/frontend/fe_wizard.py
new file mode 100644
index 0000000..777fe52
--- /dev/null
+++ b/services/frontend/fe_wizard.py
@@ -0,0 +1,216 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from datetime import datetime
+
+from selenium.webdriver.support.ui import Select
+
+from services.constants import Constants, ServiceProvider
+from services.frontend.base_actions.click import Click
+from services.frontend.base_actions.enter import Enter
+from services.frontend.base_actions.wait import Wait
+from services.helper import Helper
+from services.logging_service import LoggingServiceFactory
+from services.session import session
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class FEWizard:
+
+ E2Edate = None
+
+ @staticmethod
+ def add_vf():
+ try:
+ logger.debug("Tab Add Virtual Functions")
+ Wait.text_by_css(
+ Constants.Dashboard.Wizard.Title.CSS, Constants.Dashboard.Wizard.AddVF.Title.TEXT, wait_for_page=True)
+ vfName = "newVF" + Helper.rand_string("randomString")
+ vfVersion = "newVFVersion" + \
+ Helper.rand_string(
+ "randomNumber") + Helper.rand_string("randomString")
+ Enter.text_by_name("virtualFunction", vfName)
+ Enter.text_by_name("VFversion", vfVersion, wait_for_page=True)
+ FEWizard.date_picker_wizard()
+ Select(session.ice_driver.find_element_by_id(
+ Constants.Dashboard.Wizard.AddVF.AIC_Version.TEXT)).select_by_visible_text("AIC 3.5")
+ Select(session.ice_driver.find_element_by_id(
+ Constants.Dashboard.Wizard.AddVF.ECOMP_Release.TEXT)).select_by_visible_text("Unknown")
+ session.E2Edate = FEWizard.get_lab_entry_date()
+ Click.css(Constants.SubmitButton.CSS, wait_for_page=True)
+ Wait.page_has_loaded()
+ Wait.name_to_dissappear("Add Virtual Function")
+ return vfName
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Failed to add a Virtual Function via modal window. Exception " + \
+ str(e)
+ raise Exception(errorMsg)
+
+ @staticmethod
+ def get_lab_entry_date():
+ E2Edate = session.ice_driver.find_element_by_id(
+ "add-vf-hidden-target-lab-date").get_attribute("value")
+ return str(E2Edate)
+
+ @staticmethod
+ def add_vendor_contact():
+ logger.debug("Tab Add Vendor Contact")
+ Wait.text_by_css(Constants.Dashboard.Wizard.Title.CSS,
+ Constants.Dashboard.Wizard.AddVendorContact.Title.TEXT, wait_for_page=True)
+ Select(session.ice_driver.find_element_by_name(
+ "company")).select_by_visible_text("Ericsson")
+ fullname = Helper.rand_string(
+ "randomString") + Helper.rand_string("randomString")
+ Enter.text_by_name("fullname", fullname)
+ email = Helper.rand_string("randomString") + "@ericson.com"
+ Enter.text_by_name("email", email)
+ phone = "201" + Helper.rand_string("randomNumber", 6)
+ Enter.text_by_name("phone", phone)
+ Click.css(Constants.SubmitButton.CSS, wait_for_page=True)
+ Wait.name_to_dissappear("Add Vendor Contact", wait_for_page=True)
+ vendor = {"company": "Ericsson", "full_name": fullname,
+ "email": email, "phone": phone}
+ return vendor
+
+ @staticmethod
+ def add_service_provider_internal():
+ logger.debug(
+ "Tab Add " + ServiceProvider.MainServiceProvider + " Sponsor")
+ Wait.text_by_css(
+ Constants.Dashboard.Wizard.Title.CSS, "Add " + ServiceProvider.MainServiceProvider + " Sponsor")
+ fullname = Helper.rand_string(
+ "randomString") + Helper.rand_string("randomString")
+ Enter.text_by_name("fullname", fullname)
+ email = Helper.rand_string(
+ "randomString") + "@" + ServiceProvider.email
+ Enter.text_by_name("email", email)
+ phone = "201" + Helper.rand_string("randomNumber", 6)
+ logger.debug(phone)
+ Enter.text_by_name("phone", phone)
+ Click.css(Constants.SubmitButton.CSS)
+ Wait.name_to_dissappear("Add AT&T Sponsor")
+ sponsor = {"company": "AT&T", "full_name": fullname,
+ "email": email, "phone": phone}
+ return sponsor
+
+ @staticmethod
+ def invite_team_members(email):
+ try:
+ logger.debug("Tab Invite Team Members")
+ Wait.text_by_name(Constants.Dashboard.Wizard.InviteTeamMembers.Title.NAME,
+ Constants.Dashboard.Wizard.InviteTeamMembers.Title.TEXT)
+ Enter.text_by_name("email", email)
+ Wait.text_by_css(
+ Constants.SubmitButton.CSS, Constants.Dashboard.Wizard.InviteTeamMembers.Button.TEXT)
+ Click.css(Constants.SubmitButton.CSS)
+ Wait.name_to_dissappear(
+ Constants.Dashboard.Wizard.InviteTeamMembers.Title.NAME)
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "FAILED in Tab Invite Team Members. Exception = %s" % e
+ raise Exception(errorMsg)
+
+ @staticmethod
+ def add_ssh_key(is_negative=False):
+ logger.debug("About to add an SSH Key in modal window")
+ try: # Add SSH Key from modal window and return key value.
+ Wait.text_by_name(Constants.Dashboard.Wizard.AddSSHKey.Title.NAME,
+ Constants.Dashboard.Wizard.AddSSHKey.Title.TEXT)
+ # Generate an SSH Public Key.
+ sshKey = Helper.generate_sshpub_key()
+ if is_negative:
+ sshKey = sshKey[8:]
+ Enter.text_by_name("key", sshKey)
+
+ # Check that the submit button exists.
+ Wait.text_by_css(
+ Constants.SubmitButton.CSS, Constants.Dashboard.Wizard.AddSSHKey.Title.TEXT)
+
+ Click.css(Constants.SubmitButton.CSS) # Click on submit button.
+ if is_negative:
+ Wait.text_by_id(
+ Constants.Toast.ID, Constants.Dashboard.Avatar.Account.SSHKey.UpdateFailed.TEXT)
+ else:
+ Wait.name_to_dissappear(
+ Constants.Dashboard.Wizard.AddSSHKey.Title.NAME)
+ logger.debug("SSH Key added via modal window.")
+ return sshKey
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "Failed to add an SSH Key in the modal window. Exception=" + \
+ str(e)
+ raise Exception(errorMsg)
+
+ @staticmethod
+ def invite_team_members_modal(email):
+ try:
+ Click.id(
+ Constants.Dashboard.Overview.TeamMember.ID, wait_for_page=True)
+ Wait.text_by_css(Constants.Dashboard.Wizard.Title.CSS,
+ Constants.Dashboard.Wizard.InviteTeamMembers.Title.TEXT)
+ Enter.text_by_name("email", email)
+ Wait.text_by_css(
+ Constants.SubmitButton.CSS, Constants.Dashboard.Wizard.InviteTeamMembers.Button.TEXT)
+ Wait.css_to_dissappear(
+ '.inviteMembers-form button[disabled="disabled"].btn.btn-primary')
+ Wait.css(".inviteMembers-form button.btn.btn-primary")
+ Click.css(".inviteMembers-form button.btn.btn-primary")
+ Wait.modal_to_dissappear()
+ # If failed - count the failure and add the error to list of errors.
+ except Exception as e:
+ errorMsg = "FAILED in PopUp Invite Team Members. Exception=" + \
+ str(e)
+ raise Exception(errorMsg)
+
+ @staticmethod
+ def date_picker_add_ns(count):
+ try:
+ session.ice_driver.execute_script("var el = angular.element(document.querySelector('.addNextSteps')); el.scope().vm.nextSteps[" + str(
+ count) + "].duedate = new Date('" + str(datetime.today().isoformat()) + "')")
+ Click.css("div.modal-content", wait_for_page=True)
+ except Exception as e:
+ errorMsg = "Failed to select date with datePicker."
+
+ raise Exception(errorMsg, str(e))
+
+ @staticmethod
+ def date_picker_wizard():
+ Enter.date_picker('#e2e-lab-entry-date', 'choice.TargetLab')
+ Click.css('input[name="virtualFunction"]', wait_for_page=True)
diff --git a/services/helper.py b/services/helper.py
new file mode 100644
index 0000000..58769fe
--- /dev/null
+++ b/services/helper.py
@@ -0,0 +1,210 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+import os
+import random
+import string
+import subprocess
+import unittest
+
+from cryptography.hazmat.backends import default_backend as crypto_default_backend, \
+ default_backend
+from cryptography.hazmat.primitives import serialization as crypto_serialization
+from cryptography.hazmat.primitives.asymmetric import rsa
+from django.conf import settings
+
+from services.constants import Constants
+from services.database.db_user import DBUser
+from services.logging_service import LoggingServiceFactory
+from utils.authentication import JWTAuthentication
+
+
+logger = LoggingServiceFactory.get_logger()
+
+class Helper:
+
+ tc = unittest.TestCase('__init__')
+
+ @staticmethod
+ def rand_string(type_of_value='randomString', numberOfDigits=0):
+ letters_and_numbers = string.ascii_letters + string.digits
+ if type_of_value == 'email':
+ myEmail = ''.join(random.choice(letters_and_numbers) for _ in range(
+ 4)) + "@" + ''.join(random.choice(string.ascii_uppercase) for _ in range(4)) + ".com"
+ return "ST" + myEmail
+ elif type_of_value == 'randomNumber':
+ randomNumber = ''.join("%s" % random.randint(2, 9)
+ for _ in range(0, (numberOfDigits + 1)))
+ return randomNumber
+ elif type_of_value == 'randomString':
+ randomString = "".join(random.sample(letters_and_numbers, 5))
+ return "ST" + randomString
+ else:
+ raise Exception("invalid rand type")
+
+ @staticmethod
+ def rand_invite_email():
+ inviteEmail = "automationqatt" + \
+ Helper.rand_string("randomString") + "@gmail.com"
+ return inviteEmail
+
+ @staticmethod
+ def generate_sshpub_key():
+ try:
+ logger.debug("About to generate SSH Public Key")
+ key = rsa.generate_private_key(
+ public_exponent=65537,
+ key_size=2048,
+ backend=default_backend()
+ )
+ private_key = key.private_bytes(
+ encoding=crypto_serialization.Encoding.PEM,
+ format=crypto_serialization.PrivateFormat.TraditionalOpenSSL,
+ encryption_algorithm=crypto_serialization.NoEncryption())
+ public_key = key.public_key().public_bytes(
+ crypto_serialization.Encoding.OpenSSH,
+ crypto_serialization.PublicFormat.OpenSSH
+ ).decode("utf-8")
+
+ logger.debug("Generated SSH Public Key: " + public_key)
+ except Exception as e: # If failed write to log the error and return 'None'.
+ logger.error(e)
+ logger.error("Failed to generate SSH Public Key.")
+ raise e
+ return public_key
+
+ @staticmethod
+ def check_admin_ssh_existence(path, admin_ssh):
+ if admin_ssh == open(path).read().rstrip('\n'):
+ logger.debug(
+ "Admin SSH already defined in DB and equal to the one stored on the local system.")
+ return True
+ return False
+
+ @staticmethod
+ def get_or_create_rsa_key_for_admin():
+ try: # Create pair of keys for the given user and return his public key.
+ ssh_folder = Constants.Paths.SSH.PATH
+ public_file = ssh_folder + "id_rsa.pub"
+ privateFile = ssh_folder + "id_rsa"
+ admin_ssh_exist_and_equal = False
+ admin_ssh = None
+ if not os.path.exists(ssh_folder):
+ os.makedirs(ssh_folder)
+ elif os.path.exists(public_file):
+ admin_ssh = DBUser.retrieve_admin_ssh_from_db()
+ admin_ssh_exist_and_equal = Helper.check_admin_ssh_existence(
+ public_file, admin_ssh)
+ # TODO find pending gitlab bug causing old ssh key not be updated in gitlab cache
+ if False and admin_ssh_exist_and_equal:
+ return admin_ssh
+ else:
+ logger.debug("Private key file: " + privateFile +
+ "\nPublice key file: " + public_file)
+ key = rsa.generate_private_key(
+ backend=crypto_default_backend(),
+ public_exponent=65537,
+ key_size=2048
+ )
+ private_key = key.private_bytes(
+ crypto_serialization.Encoding.PEM,
+ crypto_serialization.PrivateFormat.PKCS8,
+ crypto_serialization.NoEncryption()).decode("utf-8")
+ public_key = key.public_key().public_bytes(
+ crypto_serialization.Encoding.OpenSSH,
+ crypto_serialization.PublicFormat.OpenSSH
+ ).decode("utf-8")
+
+ with open(privateFile, 'w') as content_file:
+ os.chmod(privateFile, 0o600)
+ content_file.write(private_key) # Save private key to file.
+ logger.debug(
+ "Private key created successfully for admin")
+ user_pub_key = public_key
+ with open(public_file, 'w') as content_file:
+ content_file.write(public_key) # Save public key to file.
+ logger.debug("Public key created successfully for admin")
+ cmd = 'ssh-keyscan ' + \
+ settings.GITLAB_URL[7:-1] + ' >> ' + \
+ ssh_folder + 'known_hosts'
+ # Create known_hosts file and add GitLab to it.
+ subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
+ logger.debug("Added GitLab to known_hosts")
+ return user_pub_key
+ except Exception as error:
+ logger.error(
+ "_-_-_-_-_- Unexpected error in get_or_create_rsa_key_for_admin: %s" % error)
+ raise Exception("Failed to create SSH keys for user admin", error)
+
+ @staticmethod
+ def internal_assert(x, y):
+ try:
+ Helper.tc.assertEqual(str(x), str(y))
+ except Exception as e:
+ raise Exception("AssertionError: \"" + str(x) +
+ "\" != \"" + str(y) + "\"", e)
+
+ @staticmethod
+ def internal_assert_boolean(x, y):
+ try:
+ Helper.tc.assertEqual(str(x), str(y))
+ return True
+ except Exception as e:
+ raise Exception("AssertionError: \"" + str(x) +
+ "\" != \"" + str(y) + "\"", e)
+
+ @staticmethod
+ def internal_not_equal(x, y):
+ try:
+ Helper.tc.assertNotEqual(x, y)
+ except Exception as e:
+ raise Exception("AssertionError: \"" + str(x) +
+ "\" != \"" + str(y) + "\"", e)
+
+ @staticmethod
+ def get_reset_passw_url(email):
+ jwtObj = JWTAuthentication()
+ token = jwtObj.createPersonalTokenWithExpiration(email)
+ resetPasswURL = Constants.Default.LoginURL.TEXT + "?t=" + token
+ return resetPasswURL
+
+ @staticmethod
+ def assertTrue(expr, msg=None):
+ """Check that the expression is true."""
+ if expr != True:
+ raise Exception("AssertionError: \"not expr")
diff --git a/services/logging_service.py b/services/logging_service.py
new file mode 100644
index 0000000..3ae7b75
--- /dev/null
+++ b/services/logging_service.py
@@ -0,0 +1,20 @@
+import logging
+
+
+class LoggingServiceFactory(object):
+ __logger = None
+
+ def __init__(self):
+ if self.__logger is None:
+ self.__set_logger()
+
+ @classmethod
+ def __set_logger(cls):
+ if cls.__logger is None:
+ cls.__logger = logging.getLogger('vvp-ci.logger')
+
+ @classmethod
+ def get_logger(cls):
+ if cls.__logger is None:
+ cls.__set_logger()
+ return cls.__logger
diff --git a/services/session.py b/services/session.py
new file mode 100644
index 0000000..174f54b
--- /dev/null
+++ b/services/session.py
@@ -0,0 +1,106 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from selenium import webdriver
+
+
+class SessionSingletone():
+ positive_wait_until_retires = 60
+ positive_wait_until_time_pause = 0.5
+ positive_wait_until_time_pause_long = 1.5
+ positive_wait_until_implicit_time = 10
+ positive_timeout = 10
+
+ negative_wait_until_retires = 5
+ negative_wait_until_time_pause = 0.5
+ negative_wait_until_implicit_time = 0.5
+ negative_timeout = 5
+
+ errorCounter = 0
+ errorList = ""
+ createTemplatecount = False
+
+ def __init__(self):
+ self.wait_until_retires = self.positive_wait_until_retires
+ self.wait_until_time_pause = self.positive_wait_until_time_pause
+ self.wait_until_time_pause_long = self.positive_wait_until_time_pause_long
+ self.wait_until_implicit_time = self.positive_wait_until_implicit_time
+ self.test = '123'
+ self.ice_driver = None
+
+ def setup_driver(self):
+ self.ice_driver = webdriver.Firefox()
+ return self.ice_driver
+
+ def get_driver(self):
+ return self.ice_driver
+
+ def close_driver(self):
+ self.ice_driver.quit()
+ self.ice_driver = None
+
+ def start_negative(self):
+ """Changing parameters to reduce negative tests run-time"""
+ self.wait_until_retires = self.negative_wait_until_retires
+ self.wait_until_time_pause = self.negative_wait_until_time_pause
+ self.wait_until_implicit_time = self.negative_wait_until_implicit_time
+ self.timeout = self.negative_timeout
+ session.ice_driver.implicitly_wait(self.wait_until_implicit_time)
+
+ def end_negative(self):
+ """Change back the parameters to suite positive tests"""
+ self.wait_until_retires = self.positive_wait_until_retires
+ self.wait_until_time_pause = self.positive_wait_until_time_pause
+ self.wait_until_implicit_time = self.positive_wait_until_implicit_time
+ self.timeout = self.positive_timeout
+ session.ice_driver.implicitly_wait(self.wait_until_implicit_time)
+
+ def run_negative(self, run_me, error_msg):
+ self.start_negative()
+ try:
+ run_me() # click.css
+ except:
+ # will run if click does NOT succeed
+ self.errorCounter = 0
+ self.errorList = ""
+ else:
+ # will run if click SUCCEED
+ raise Exception(error_msg)
+ self.end_negative()
+
+session = SessionSingletone()
diff --git a/services/types.py b/services/types.py
new file mode 100644
index 0000000..7dbbe94
--- /dev/null
+++ b/services/types.py
@@ -0,0 +1,91 @@
+
+# ============LICENSE_START==========================================
+# org.onap.vvp/test-engine
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the “License”);
+# you may not use this software except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the “License”);
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+from services.api.api_bridge import APIBridge
+from services.api.api_checklist import APIChecklist
+from services.api.api_gitlab import APIGitLab
+from services.api.api_jenkins import APIJenkins
+from services.api.api_user import APIUser
+from services.api.api_virtual_function import APIVirtualFunction
+from services.database.db_checklist import DBChecklist
+from services.database.db_cms import DBCMS
+from services.database.db_general import DBGeneral
+from services.database.db_user import DBUser
+from services.database.db_virtual_function import DBVirtualFunction
+from services.frontend.fe_checklist import FEChecklist
+from services.frontend.fe_cms import FECms
+from services.frontend.fe_dashboard import FEDashboard
+from services.frontend.fe_detailed_view import FEDetailedView
+from services.frontend.fe_general import FEGeneral
+from services.frontend.fe_invite import FEInvite
+from services.frontend.fe_overview import FEOverview
+from services.frontend.fe_user import FEUser
+from services.frontend.fe_wizard import FEWizard
+from services.frontend.fe_checklist_template import FEChecklistTemplate
+from services.api.api_rados import APIRados
+
+
+class Frontend:
+ User = FEUser()
+ Invite = FEInvite()
+ Checklist = FEChecklist()
+ Dashboard = FEDashboard()
+ DetailedView = FEDetailedView()
+ General = FEGeneral()
+ Overview = FEOverview()
+ Wizard = FEWizard()
+ Cms = FECms()
+ ChecklistTemplate = FEChecklistTemplate()
+
+
+class API:
+ Bridge = APIBridge()
+ Checklist = APIChecklist()
+ GitLab = APIGitLab()
+ Jenkins = APIJenkins()
+ Rados = APIRados
+ User = APIUser()
+ VirtualFunction = APIVirtualFunction()
+
+
+class DB:
+ Checklist = DBChecklist()
+ Cms = DBCMS()
+ General = DBGeneral()
+ User = DBUser()
+ VirtualFunction = DBVirtualFunction()