diff options
Diffstat (limited to 'testapi/opnfv_testapi')
75 files changed, 6742 insertions, 1647 deletions
diff --git a/testapi/opnfv_testapi/common/check.py b/testapi/opnfv_testapi/common/check.py index 333871d..fdc527f 100644 --- a/testapi/opnfv_testapi/common/check.py +++ b/testapi/opnfv_testapi/common/check.py @@ -21,7 +21,8 @@ from opnfv_testapi.db import api as dbapi def is_authorized(method): @functools.wraps(method) def wrapper(self, *args, **kwargs): - if CONF.api_authenticate and self.table in ['pods', 'projects', 'testcases']: + resources = ['pods', 'projects', 'testcases', 'scenarios'] + if CONF.api_authenticate and self.table in resources: testapi_id = self.get_secure_cookie(constants.TESTAPI_ID) if not testapi_id: raises.Unauthorized(message.not_login()) @@ -29,17 +30,23 @@ def is_authorized(method): if not user_info: raises.Unauthorized(message.not_lfid()) if method.__name__ == "_create": - kwargs['owner'] = testapi_id - if self.table in ['projects']: + kwargs['creator'] = testapi_id + if self.table in ['projects', 'testcases']: + map_name = { + 'projects': 'name', + 'testcases': 'project_name' + } + group = "opnfv-gerrit-{}-submitters" query = kwargs.get('query') if type(query) is not dict: query_data = query() else: - if self.json_args is None: + if (self.json_args is None or + map_name[self.table] not in self.json_args): query_data = query else: query_data = self.json_args - group = "opnfv-gerrit-" + query_data['name'] + "-submitters" + group = group.format(query_data[map_name[self.table]]) if group not in user_info['groups']: raises.Unauthorized(message.no_permission()) ret = yield gen.coroutine(method)(self, *args, **kwargs) @@ -47,6 +54,32 @@ def is_authorized(method): return wrapper +def is_reource_tied(method): + @functools.wraps(method) + def wrapper(self, *args, **kwargs): + query_data = {} + tied_maps = { + 'projects': ('testcases', 'project_name'), + 'pods': ('results', 'pod_name'), + 'testcases': ('results', 'case_name') + } + if self.table in tied_maps: + if method.__name__ == '_update': + if 'name' in self.json_args: + if self.json_args['name'] == kwargs.get('query')['name']: + ret = yield gen.coroutine(method)( + self, *args, **kwargs) + raise gen.Return(ret) + query_data[tied_maps[self.table][1]] = kwargs.get('query')['name'] + data = yield dbapi.db_find_one( + tied_maps[self.table][0], query_data) + if data: + raises.Unauthorized(message.tied_with_resource()) + ret = yield gen.coroutine(method)(self, *args, **kwargs) + raise gen.Return(ret) + return wrapper + + def valid_token(method): @functools.wraps(method) def wrapper(self, *args, **kwargs): @@ -136,8 +169,10 @@ def new_not_exists(xstep): if query: query_data = query() if self.table == 'pods': - if query_data.get('name') is not None: - query_data['name'] = re.compile('\\b' + query_data.get('name') + '\\b', re.IGNORECASE) + if query_data.get('name'): + query_data['name'] = re.compile( + '\\b{}\\b'.format(query_data.get('name')), + re.IGNORECASE) to_data = yield dbapi.db_find_one(self.table, query_data) if to_data: raises.Forbidden(message.exist(self.table, query())) @@ -165,7 +200,9 @@ def query_by_name(xstep): def wrap(self, *args, **kwargs): if 'name' in self.request.query_arguments.keys(): query = kwargs.get('query', {}) - query.update({'name': re.compile(self.get_query_argument('name'), re.IGNORECASE)}) + query.update({ + 'name': re.compile(self.get_query_argument('name'), + re.IGNORECASE)}) kwargs.update({'query': query}) ret = yield gen.coroutine(xstep)(self, *args, **kwargs) diff --git a/testapi/opnfv_testapi/common/constants.py b/testapi/opnfv_testapi/common/constants.py index 70c9223..c7f82d9 100644 --- a/testapi/opnfv_testapi/common/constants.py +++ b/testapi/opnfv_testapi/common/constants.py @@ -1,4 +1,3 @@ TESTAPI_ID = 'testapi_id' CSRF_TOKEN = 'csrf_token' -ROLE = 'role' TESTAPI_USERS = ['opnfv-testapi-users'] diff --git a/testapi/opnfv_testapi/common/message.py b/testapi/opnfv_testapi/common/message.py index b92b7f0..52cc2ad 100644 --- a/testapi/opnfv_testapi/common/message.py +++ b/testapi/opnfv_testapi/common/message.py @@ -10,10 +10,6 @@ not_found_base = 'Could Not Found' exist_base = 'Already Exists' -def key_error(key): - return "KeyError: '{}'".format(key) - - def no_body(): return 'No Body' @@ -64,3 +60,7 @@ def must_int(name): def no_permission(): return 'You do not have permission to perform this action' + + +def tied_with_resource(): + return 'Selected resource is associated with other resources' diff --git a/testapi/opnfv_testapi/handlers/base_handlers.py b/testapi/opnfv_testapi/handlers/base_handlers.py index 9eac737..3dbd53a 100644 --- a/testapi/opnfv_testapi/handlers/base_handlers.py +++ b/testapi/opnfv_testapi/handlers/base_handlers.py @@ -79,8 +79,8 @@ class GenericApiHandler(web.RequestHandler): @check.valid_token @check.no_body @check.miss_fields - @check.new_not_exists @check.is_authorized + @check.new_not_exists @check.values_check @check.carriers_exist def _create(self, **kwargs): @@ -179,6 +179,7 @@ class GenericApiHandler(web.RequestHandler): @gen.coroutine @check.not_exist @check.is_authorized + @check.is_reource_tied def _delete(self, data, query=None): yield dbapi.db_delete(self.table, query) self.finish_request() @@ -189,6 +190,7 @@ class GenericApiHandler(web.RequestHandler): @check.not_exist @check.updated_one_not_exist @check.is_authorized + @check.is_reource_tied def _update(self, data, query=None, **kwargs): data = self.table_cls.from_dict(data) update_req = self._update_requests(data) @@ -200,6 +202,7 @@ class GenericApiHandler(web.RequestHandler): @gen.coroutine @check.no_body @check.not_exist + @check.is_authorized @check.updated_one_not_exist def pure_update(self, data, query=None, **kwargs): data = self.table_cls.from_dict(data) diff --git a/testapi/opnfv_testapi/handlers/deploy_result_handlers.py b/testapi/opnfv_testapi/handlers/deploy_result_handlers.py index 973bfef..a8fcd88 100644 --- a/testapi/opnfv_testapi/handlers/deploy_result_handlers.py +++ b/testapi/opnfv_testapi/handlers/deploy_result_handlers.py @@ -1,6 +1,7 @@ from opnfv_testapi.handlers import result_handlers from opnfv_testapi.models import deploy_result_models from opnfv_testapi.tornado_swagger import swagger +from bson import objectid class GenericDeployResultHandler(result_handlers.GenericResultHandler): @@ -113,3 +114,17 @@ class DeployResultsHandler(GenericDeployResultHandler): self._create(miss_fields=miss_fields, carriers=carriers, values_check=values_check) + + +class DeployResultHandler(GenericDeployResultHandler): + @swagger.operation(nickname='getTestDeployResultById') + def get(self, result_id): + """ + @description: get a single deploy result by result_id + @rtype: L{DeployResult} + @return 200: Deploy result exist + @raise 404: Deploy result not exist + """ + query = dict() + query["_id"] = objectid.ObjectId(result_id) + self._get_one(query=query) diff --git a/testapi/opnfv_testapi/handlers/result_handlers.py b/testapi/opnfv_testapi/handlers/result_handlers.py index b0691cd..edcac6e 100644 --- a/testapi/opnfv_testapi/handlers/result_handlers.py +++ b/testapi/opnfv_testapi/handlers/result_handlers.py @@ -8,12 +8,9 @@ ############################################################################## from datetime import datetime from datetime import timedelta -import json -import logging from bson import objectid -from opnfv_testapi.common import constants from opnfv_testapi.common import message from opnfv_testapi.common import raises from opnfv_testapi.common.config import CONF @@ -41,7 +38,6 @@ class GenericResultHandler(base_handlers.GenericApiHandler): query = dict() date_range = dict() - query['public'] = {'$not': {'$eq': 'false'}} for k in self.request.query_arguments.keys(): v = self.get_query_argument(k) if k == 'project' or k == 'pod' or k == 'case': @@ -52,21 +48,12 @@ class GenericResultHandler(base_handlers.GenericApiHandler): period = datetime.now() - timedelta(days=v) obj = {"$gte": str(period)} query['start_date'] = obj - elif k == 'trust_indicator': - query[k + '.current'] = float(v) elif k == 'from': date_range.update({'$gte': str(v)}) elif k == 'to': date_range.update({'$lt': str(v)}) elif 'build_id' in k: query[k] = self.get_int(k, v) - elif k == 'signed': - username = self.get_secure_cookie(constants.TESTAPI_ID) - role = self.get_secure_cookie(constants.ROLE) - if role: - del query['public'] - if role != "reviewer": - query['user'] = username elif k not in ['last', 'page', 'descend']: query[k] = v if date_range: @@ -119,12 +106,9 @@ class ResultsCLHandler(GenericResultHandler): - to : ending time in 2016-01-01 or 2016-01-01 00:01:23 - scenario : the test scenario (previously version) - criteria : the global criteria status passed or failed - - trust_indicator : evaluate the stability of the test case - to avoid running systematically long and stable test case - - signed : get logined user result GET /results/project=functest&case=vPing&version=Arno-R1 \ - &pod=pod_name&period=15&signed + &pod=pod_name&period=15 @return 200: all test results consist with query, empty list if no result is found @rtype: L{TestResults} @@ -180,14 +164,6 @@ class ResultsCLHandler(GenericResultHandler): @type page: L{int} @in page: query @required page: False - @param trust_indicator: must be float - @type trust_indicator: L{float} - @in trust_indicator: query - @required trust_indicator: False - @param signed: user results or all results - @type signed: L{string} - @in signed: query - @required signed: False @param descend: true, newest2oldest; false, oldest2newest @type descend: L{string} @in descend: query @@ -231,36 +207,8 @@ class ResultsCLHandler(GenericResultHandler): values_check=values_check) -class ResultsUploadHandler(ResultsCLHandler): - @swagger.operation(nickname="uploadTestResult") - def post(self): - """ - @description: upload and create a test result - @param body: result to be created - @type body: L{ResultCreateRequest} - @in body: body - @rtype: L{CreateResponse} - @return 200: result is created. - @raise 404: pod/project/testcase not exist - @raise 400: body/pod_name/project_name/case_name not provided - """ - logging.info('file upload') - fileinfo = self.request.files['file'][0] - is_public = self.get_body_argument('public') - logging.warning('public:%s', is_public) - logging.info('results is :%s', fileinfo['filename']) - logging.info('results is :%s', fileinfo['body']) - self.json_args = json.loads(fileinfo['body']).copy() - self.json_args['public'] = is_public - - openid = self.get_secure_cookie(constants.TESTAPI_ID) - if openid: - self.json_args['user'] = openid - - super(ResultsUploadHandler, self).post() - - class ResultsGURHandler(GenericResultHandler): + @swagger.operation(nickname='getTestResultById') def get(self, result_id): """ @@ -272,19 +220,3 @@ class ResultsGURHandler(GenericResultHandler): query = dict() query["_id"] = objectid.ObjectId(result_id) self._get_one(query=query) - - @swagger.operation(nickname="updateTestResultById") - def put(self, result_id): - """ - @description: update a single result by _id - @param body: fields to be updated - @type body: L{ResultUpdateRequest} - @in body: body - @rtype: L{Result} - @return 200: update success - @raise 404: result not exist - @raise 403: nothing to update - """ - query = {'_id': objectid.ObjectId(result_id)} - db_keys = [] - self._update(query=query, db_keys=db_keys) diff --git a/testapi/opnfv_testapi/handlers/sign_handlers.py b/testapi/opnfv_testapi/handlers/sign_handlers.py index 7540662..2039971 100644 --- a/testapi/opnfv_testapi/handlers/sign_handlers.py +++ b/testapi/opnfv_testapi/handlers/sign_handlers.py @@ -46,7 +46,7 @@ class SigninReturnHandler(SignBaseHandler): dbapi.db_update(self.table, q_user, login_user) self.clear_cookie(constants.TESTAPI_ID) - self.set_secure_cookie(constants.TESTAPI_ID, user) + self.set_secure_cookie(constants.TESTAPI_ID, user, 1) self.redirect(url=CONF.ui_url) diff --git a/testapi/opnfv_testapi/models/pod_models.py b/testapi/opnfv_testapi/models/pod_models.py index 0eddfcc..8af5297 100644 --- a/testapi/opnfv_testapi/models/pod_models.py +++ b/testapi/opnfv_testapi/models/pod_models.py @@ -30,7 +30,7 @@ class Pod(PodCreateRequest): def __init__(self, **kwargs): self._id = kwargs.pop('_id', '') self.creation_date = kwargs.pop('creation_date', '') - self.owner = kwargs.pop('owner', '') + self.creator = kwargs.pop('creator', '') super(Pod, self).__init__(**kwargs) diff --git a/testapi/opnfv_testapi/models/project_models.py b/testapi/opnfv_testapi/models/project_models.py index 5f280f1..5c8c048 100644 --- a/testapi/opnfv_testapi/models/project_models.py +++ b/testapi/opnfv_testapi/models/project_models.py @@ -27,11 +27,16 @@ class ProjectUpdateRequest(base_models.ModelBase): @swagger.model() class Project(base_models.ModelBase): def __init__(self, - name=None, _id=None, description=None, create_date=None): + name=None, + creator='', + _id=None, + description=None, + creation_date=None): + self.creator = creator self._id = _id self.name = name self.description = description - self.creation_date = create_date + self.creation_date = creation_date @swagger.model() diff --git a/testapi/opnfv_testapi/models/result_models.py b/testapi/opnfv_testapi/models/result_models.py index 1dbe729..602318a 100644 --- a/testapi/opnfv_testapi/models/result_models.py +++ b/testapi/opnfv_testapi/models/result_models.py @@ -11,45 +11,7 @@ from opnfv_testapi.tornado_swagger import swagger @swagger.model() -class TIHistory(base_models.ModelBase): - """ - @ptype step: L{float} - """ - def __init__(self, date=None, step=0): - self.date = date - self.step = step - - -@swagger.model() -class TI(base_models.ModelBase): - """ - @property histories: trust_indicator update histories - @ptype histories: C{list} of L{TIHistory} - @ptype current: L{float} - """ - def __init__(self, current=0): - self.current = current - self.histories = list() - - def __eq__(self, other): - return (self.current == other.current and self._histories_eq(other)) - - def _histories_eq(self, other): - hs_equal = all(self.histories[i] == other.histories[i] - for i in range(len(self.histories))) - return len(self.histories) == len(other.histories) and hs_equal - - @staticmethod - def attr_parser(): - return {'histories': TIHistory} - - -@swagger.model() class ResultCreateRequest(base_models.ModelBase): - """ - @property trust_indicator: - @ptype trust_indicator: L{TI} - """ def __init__(self, pod_name=None, project_name=None, @@ -61,10 +23,7 @@ class ResultCreateRequest(base_models.ModelBase): details=None, build_tag=None, scenario=None, - criteria=None, - user=None, - public="true", - trust_indicator=None): + criteria=None): self.pod_name = pod_name self.project_name = project_name self.case_name = case_name @@ -76,37 +35,15 @@ class ResultCreateRequest(base_models.ModelBase): self.build_tag = build_tag self.scenario = scenario self.criteria = criteria - self.user = user - self.public = public - self.trust_indicator = trust_indicator if trust_indicator else TI(0) def __eq__(self, other): - simple_equal = all(getattr(self, k) == getattr(other, k) - for k in self.format().keys() - if k not in ['_id', 'trust_indicator']) - return simple_equal and self.trust_indicator == other.trust_indicator - - @staticmethod - def attr_parser(): - return {'trust_indicator': TI} - - -@swagger.model() -class ResultUpdateRequest(base_models.ModelBase): - """ - @property trust_indicator: - @ptype trust_indicator: L{TI} - """ - def __init__(self, trust_indicator=None): - self.trust_indicator = trust_indicator + return all(getattr(self, k) == getattr(other, k) + for k in self.format().keys() + if k not in ['_id']) @swagger.model() class TestResult(ResultCreateRequest): - """ - @property trust_indicator: used for long duration test case - @ptype trust_indicator: L{TI} - """ def __init__(self, _id=None, **kwargs): super(TestResult, self).__init__(**kwargs) self._id = _id diff --git a/testapi/opnfv_testapi/models/scenario_models.py b/testapi/opnfv_testapi/models/scenario_models.py index 0610c6b..537650e 100644 --- a/testapi/opnfv_testapi/models/scenario_models.py +++ b/testapi/opnfv_testapi/models/scenario_models.py @@ -178,10 +178,16 @@ class Scenario(base_models.ModelBase): @property installers: @ptype installers: C{list} of L{ScenarioInstaller} """ - def __init__(self, name='', create_date='', _id='', installers=None): + def __init__(self, + name='', + creation_date='', + _id='', + creator='', + installers=None): self.name = name + self.creator = creator self._id = _id - self.creation_date = create_date + self.creation_date = creation_date self.installers = list_default(installers) @staticmethod diff --git a/testapi/opnfv_testapi/router/url_mappings.py b/testapi/opnfv_testapi/router/url_mappings.py index a857725..8f01a66 100644 --- a/testapi/opnfv_testapi/router/url_mappings.py +++ b/testapi/opnfv_testapi/router/url_mappings.py @@ -49,9 +49,9 @@ mappings = [ # Push results with mandatory request payload parameters # (project, case, and pod) (r"/api/v1/results", result_handlers.ResultsCLHandler), - (r'/api/v1/results/upload', result_handlers.ResultsUploadHandler), (r"/api/v1/results/([^/]+)", result_handlers.ResultsGURHandler), (r"/api/v1/deployresults", deploy_handlers.DeployResultsHandler), + (r"/api/v1/deployresults/([^/]+)", deploy_handlers.DeployResultHandler), # scenarios (r"/api/v1/scenarios", scenario_handlers.ScenariosCLHandler), diff --git a/testapi/opnfv_testapi/tests/UI/e2e/authenticateFalseSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/authenticateFalseSpec.js new file mode 100644 index 0000000..6b9a2bf --- /dev/null +++ b/testapi/opnfv_testapi/tests/UI/e2e/authenticateFalseSpec.js @@ -0,0 +1,540 @@ + +var mock = require('protractor-http-mock'); +var baseURL = "http://localhost:8000/"; + + +describe('testing the pods page for anonymous user', function () { + beforeEach(function(){ + mock([{ + request: { + path: '/api/v1/pods', + method: 'GET' + }, + response: { + data: { + pods: [{role: "community-ci", name: "test", owner: "testUser", + details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed", + creation_date: "2017-10-25 11:58:25.926168"}] + } + } + } + ]); + }); + + afterEach(function(){ + mock.teardown(); + }); + + it('Delete button is visible for anonymous user', function () { + var fs = require('fs') + var m = JSON.parse(fs.readFileSync('testapi-ui/config.json').toString()); + m.authenticate = false; + fs.writeFile('testapi-ui/config.json', JSON.stringify(m, null, 2)) + browser.restart(); + browser.get(baseURL+'#/pods'); + var buttonDelete = element(by.buttonText('Delete')); + expect(buttonDelete.isDisplayed()).toBe(true) + }); + + it('Delete button is visible for anonymous user', function () { + var buttonDelete = element(by.buttonText('Delete')); + expect(buttonDelete.isDisplayed()).toBe(true) + }); + + it('delete Operation is visible for user ', function () { + var deleteOperation = element(by.css('a[title=Delete]')); + expect(deleteOperation.isDisplayed()).toBe(true); + }); +}); + +describe('testing the project page for anonymous user', function () { + beforeEach(function(){ + mock([ + { + request: { + path: '/api/v1/projects', + method: 'GET' + }, + response: { + data: { + "projects": [ + { + "owner": "thuva4", + "_id": "5a0c022f9a07c846d3c2cc94", + "creation_date": "2017-11-15 14:30:31.200259", + "description": "dsfsd", + "name": "testproject" + } + ] + } + } + } + ]); + }); + + afterEach(function(){ + mock.teardown(); + }); + + it('create button is visible for user', function () { + browser.get(baseURL+'#/projects'); + var buttonCreate = element(by.buttonText('Create')); + expect(buttonCreate.isDisplayed()).toBe(true); + }); + + it('delete Operation is visible for user ', function () { + browser.get(baseURL+'#/projects'); + var deleteOperation = element(by.css('a[title=Delete]')); + expect(deleteOperation.isDisplayed()).toBe(true); + }); + + it('Edit Operation is visible for user ', function () { + browser.get(baseURL+'#/projects'); + var editOperation = element(by.css('a[title=Edit]')); + expect(editOperation.isDisplayed()).toBe(true); + }); +}); + + +describe('testing the scenarios page for anonymous user', function () { + beforeEach(function(){ + mock([ + { + request: { + path: '/api/v1/scenarios', + method: 'GET' + }, + response: { + data: { + "scenarios": [ + { + "installers": [ + { + "installer": "fuel", + "versions": [ + { + "owner": "testUser", + "version": "colorado", + "projects": [ + { + "project": "yardstick", + "customs": [ + "dvs" + ], + "scores": [ + { + "date": "2016-12-11 01:45", + "score": "14/24" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + } + ] + }, + { + "project": "functest", + "customs": [ + "vping_ssh", + "vping_userdata", + ], + "scores": [ + { + "date": "2016-12-09 11:28", + "score": "6/8" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + } + ] + }, + { + "project": "sla", + "customs": [], + "scores": [ + { + "date": "2018-01-16T18:30:00.000Z", + "score": "sdS" + } + ], + "trust_indicators": [] + }, + { + "project": "dvsd", + "customs": [], + "scores": [], + "trust_indicators": [] + } + ] + }, + { + "owner": "dfgvds", + "version": "df", + "projects": [] + } + ] + }, + { + "installer": "fuel2", + "versions": [ + { + "owner": "testUser", + "version": "colorado", + "projects": [ + { + "project": "yardstick", + "customs": [ + "tc002", + "tc005", + "tc010", + "tc011" + ], + "scores": [ + { + "date": "2016-12-11 01:45", + "score": "14/24" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + } + ] + }, + { + "project": "functest", + "customs": [ + "vping_ssh", + "vping_userdata" + ], + "scores": [ + { + "date": "2016-12-09 11:28", + "score": "6/8" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + } + ] + } + ] + } + ] + } + ], + "_id": "5a50fcacsdgdsgdasgfvb861c", + "name": "test-scenario", + "creation_date": "2018-01-06 22:13:24.160407" + } + ] + } + } + } + ]) + }); + + afterEach(function(){ + mock.teardown(); + }); + + it( 'should show the add installer option for anonymous user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var buttonAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[2]/button')) + expect(buttonAdd.isDisplayed()).toBe(true); + }); + + it( 'should show the delete installer option for user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[3]/button')) + expect(installerDelete.isDisplayed()).toBe(true); + }); + + it( 'should show the add version option for user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[2]/button')) + versionAdd.click() + expect(versionAdd.isDisplayed()).toBe(true); + }); + + it( 'should show the delete version option for user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var versionDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody[1]/tr[1]/td[3]/button')) + expect(versionDelete.isDisplayed()).toBe(true); + }); + + it( 'should show the add project option for user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[2]/button')) + projectAdd.click() + expect(projectAdd.isDisplayed()).toBe(true); + }); + + it( 'should show the delete project option for user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[1]/td[3]/button')) + projectDelete.click() + expect(projectDelete.isDisplayed()).toBe(true); + }); + + it( 'should show the add customs option for user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + projectShow.click(); + var customsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/a/p')) + customsShow.click(); + var row = element.all(by.repeater('(indexCU, custom) in project.customs')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("dvs"); + var buttonAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/button')) + buttonAdd.click() + expect(buttonAdd.isDisplayed()).toBe(true); + }); + + it( 'should show the delete customs option for user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + projectShow.click(); + var customsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/a/p')) + customsShow.click(); + var row = element.all(by.repeater('(indexCU, custom) in project.customs')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("dvs"); + var buttonDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/table/tbody/tr[1]/td[2]/button')) + buttonDelete.click() + expect(buttonDelete.isDisplayed()).toBe(true); + }); +}); + + +describe('testing the testCases page for anonymous user', function () { + beforeEach(function(){ + mock([ + { + request: { + path: '/api/v1/projects', + method: 'GET' + }, + response: { + data: { + "projects": [ + { + "creator": "thuva4", + "_id": "5a0c022f9a07c846d3c2cc94", + "creation_date": "2017-11-15 14:30:31.200259", + "description": "dsfsd", + "name": "testproject" + } + ] + } + } + }, + { + request: { + path: '/api/v1/projects/testproject', + method: 'GET' + }, + response: { + data: { + "creator": "thuva4", + "_id": "5a0c022f9a07c846d3c2cc94", + "creation_date": "2017-11-15 14:30:31.200259", + "description": "dsfsd", + "name": "testproject" + } + } + }, + { + request: { + path: '/api/v1/projects/testproject/cases', + method: 'GET' + }, + response: { + data: { + "testcases": [ + { + "project_name": "testproject", + "run": null, + "description": null, + "tags": null, + "creation_date": "2017-12-20 18:47:04.025544", + "dependencies": null, + "tier": null, + "trust": null, + "blocking": null, + "name": "testCase", + "ci_loop": null, + "url": null, + "version": null, + "criteria": null, + "domains": null, + "_id": "5a3a62d09a07c836e06858fb", + "catalog_description": null + } + ] + } + } + }, + { + request: { + path: '/api/v1/projects/testproject/cases/testCase', + method: 'GET' + }, + response: { + data: { + "project_name": "testproject", + "run": null, + "description": null, + "tags": null, + "creation_date": "2017-12-20 18:47:04.025544", + "dependencies": null, + "tier": null, + "trust": null, + "blocking": null, + "name": "testCase", + "ci_loop": null, + "url": null, + "version": null, + "criteria": null, + "domains": null, + "_id": "5a3a62d09a07c836e06858fb", + "catalog_description": null + } + } + } + ]); + }); + + afterEach(function(){ + mock.teardown(); + }); + + it( 'should show the testCases for anonymous user', function() { + browser.get(baseURL+"#/projects/testproject"); + var testCases = element(by.linkText('Test Cases')); + testCases.click(); + var row = element.all(by.repeater('(index, testcase) in testCasesCtrl.data.testcases')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("testCase"); + }); + + it( 'navigate anonymous user to testCase page', function() { + browser.get(baseURL+"#/projects/testproject"); + var testCases = element(by.linkText('Test Cases')); + testCases.click(); + var testCase = element(by.linkText('testCase')); + testCase.click(); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/projects/testproject/testCase'), 10000); + }); + + it('create button is visible for anonymous user ', function () { + browser.get(baseURL+"#/projects/testproject"); + var testCases = element(by.linkText('Test Cases')); + testCases.click(); + var buttonCreate = element(by.buttonText('Create')); + expect(buttonCreate.isDisplayed()).toBe(true); + }); + + it('Delete button is not visible for anonymous user ', function () { + browser.get(baseURL+"#/projects/testproject"); + var testCases = element(by.linkText('Test Cases')); + testCases.click(); + var buttonDelete = element(by.buttonText('Delete')); + expect(buttonDelete.isDisplayed()).toBe(true); + }); + + it('delete Operation is visible for anonymous user ', function () { + browser.get(baseURL+"#/projects/testproject"); + var testCases = element(by.linkText('Test Cases')); + testCases.click(); + var deleteOperation = element(by.css('a[title=Delete]')); + expect(deleteOperation.isDisplayed()).toBe(true); + }); + + it('Edit Operation is visible for anonymous user ', function () { + browser.get(baseURL+"#/projects/testproject"); + var testCases = element(by.linkText('Test Cases')); + testCases.click(); + var editOperation = element(by.css('a[title=Edit]')); + expect(editOperation.isDisplayed()).toBe(true); + }); +}); + + diff --git a/testapi/opnfv_testapi/tests/UI/e2e/deployResultsControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/deployResultsControllerSpec.js new file mode 100644 index 0000000..40f60e4 --- /dev/null +++ b/testapi/opnfv_testapi/tests/UI/e2e/deployResultsControllerSpec.js @@ -0,0 +1,397 @@ +'use strict'; + +var mock = require('protractor-http-mock'); +var baseURL = "http://localhost:8000/" + +describe('testing the result page for anonymous user', function () { + beforeEach(function(){ + mock([ + { + request: { + path: '/api/v1/pods', + method: 'GET' + }, + response: { + data: { + pods: [{role: "community-ci", name: "test", owner: "testUser", + details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed", + creation_date: "2017-10-25 11:58:25.926168"}] + } + } + }, + { + request: { + path: '/api/v1/deployresults', + method: 'GET', + queryString: { + page: '1' + } + }, + response: { + data: { + "pagination": { + "current_page": 1, + "total_pages": 1 + }, + "deployresults": [ + { + "build_id": 411, + "upstream_build_id": 184, + "scenario": "os-nosdn-nofeature-ha", + "stop_date": "2018-01-2723:21:31.3N", + "start_date": "2018-01-2723:21:28.3N", + "upstream_job_name": "daisy-os-nosdn-nofeature-ha-baremetal-daily-master", + "version": "master", + "pod_name": "zte-pod", + "criteria": "PASS", + "installer": "daisy", + "_id": "5a6dc1089a07c80f3c9f8d62", + "job_name": "daisy-deploy-baremetal-daily-master", + "details": null + } + ] + } + } + }, + { + request: { + path: '/api/v1/deployresults', + method: 'GET', + queryString: { + page: '1', + installer: 'daisy' + } + }, + response: { + data: { + "pagination": { + "current_page": 1, + "total_pages": 1 + }, + "deployresults": [ + { + "build_id": 411, + "upstream_build_id": 184, + "scenario": "os-nosdn-nofeature-ha", + "stop_date": "2018-01-2723:21:31.3N", + "start_date": "2018-01-2723:21:28.3N", + "upstream_job_name": "daisy-os-nosdn-nofeature-ha-baremetal-daily-master", + "version": "master", + "pod_name": "zte-pod", + "criteria": "PASS", + "installer": "daisy", + "_id": "5a6dc1089a07c80f3c9f8d63", + "job_name": "daisy-deploy-baremetal-daily-master", + "details": null + } + ] + } + } + }, + { + request: { + path: '/api/v1/deployresults', + method: 'GET', + queryString: { + page: '1', + installer: 'daisy', + job_name: 'daisy-deploy-baremetal-daily-master' + } + }, + response: { + data: { + "pagination": { + "current_page": 1, + "total_pages": 1 + }, + "deployresults": [ + { + "build_id": 411, + "upstream_build_id": 184, + "scenario": "os-nosdn-nofeature-ha", + "stop_date": "2018-01-2723:21:31.3N", + "start_date": "2018-01-2723:21:28.3N", + "upstream_job_name": "daisy-os-nosdn-nofeature-ha-baremetal-daily-master", + "version": "master", + "pod_name": "zte-pod", + "criteria": "PASS", + "installer": "daisy", + "_id": "5a6dc1089a07c80f3c9f8d64", + "job_name": "daisy-deploy-baremetal-daily-master", + "details": null + } + ] + } + } + } + ]); + }); + + afterEach(function(){ + mock.teardown(); + }); + + it( 'should show the deploy results page for anonymous user', function() { + browser.get(baseURL+"#/deployresults"); + expect(element(by.cssContainingText(".ng-binding.ng-scope","Deploy Results")).isDisplayed()).toBe(true); + }); + + it( 'navigate anonymous user to results page', function() { + browser.get(baseURL); + var resultLink = element(by.linkText('Deploy Results')).click(); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/deployresults'), 10000); + }); + + it('Should show the results in results page for anonymous user ', function () { + browser.get(baseURL+"#/deployresults"); + var row = element.all(by.repeater('(index, result) in ctrl.data.deployresults')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("3c9f8d62"); + }); + + it('Should show the results in results page related to the filters for anonymous user ', function () { + browser.get(baseURL+"#/deployresults"); + var filter = element(by.model('ctrl.filter')); + var filterText = element(by.model('ctrl.filterText')); + filter.sendKeys('installer'); + filterText.sendKeys('daisy'); + var buttonFilter = element(by.buttonText('Filter')); + buttonFilter.click(); + var row = element.all(by.repeater('(index, result) in ctrl.data.deployresults')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("3c9f8d63"); + filter.sendKeys('job_name'); + filterText.sendKeys('daisy-deploy-baremetal-daily-master') + buttonFilter.click(); + expect(cells.get(0).getText()).toContain("3c9f8d64"); + }); + it('Should not show the results in results page related to the filters for anonymous user ', function () { + browser.get(baseURL+"#/deployresults"); + var filter = element(by.model('ctrl.filter')); + var filterText = element(by.model('ctrl.filterText')); + filter.sendKeys('installer'); + filterText.sendKeys('daisyl'); + var buttonFilter = element(by.buttonText('Filter')); + buttonFilter.click(); + expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope')) + .isDisplayed()).toBe(true); + }); + +}); + +describe('testing the result page for user', function () { + beforeEach(function(){ + mock([ + { + request: { + path: '/api/v1/pods', + method: 'GET' + }, + response: { + data: { + pods: [{role: "community-ci", name: "test", owner: "testUser", + details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed", + creation_date: "2017-10-25 11:58:25.926168"}] + } + } + }, + { + request: { + path: '/api/v1/profile', + method: 'GET' + }, + response: { + data: { + "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", + "user": "testUser", "groups": ["opnfv-testapi-users"], + "email": "testuser@test.com" + } + } + }, + { + request: { + path: '/api/v1/deployresults', + method: 'GET', + queryString: { + page: '1' + } + }, + response: { + data: { + "pagination": { + "current_page": 1, + "total_pages": 1 + }, + "deployresults": [ + { + "build_id": 411, + "upstream_build_id": 184, + "scenario": "os-nosdn-nofeature-ha", + "stop_date": "2018-01-2723:21:31.3N", + "start_date": "2018-01-2723:21:28.3N", + "upstream_job_name": "daisy-os-nosdn-nofeature-ha-baremetal-daily-master", + "version": "master", + "pod_name": "zte-pod", + "criteria": "PASS", + "installer": "daisy", + "_id": "5a6dc1089a07c80f3c9f8d62", + "job_name": "daisy-deploy-baremetal-daily-master", + "details": null + } + ] + } + } + }, + { + request: { + path: '/api/v1/deployresults', + method: 'GET', + queryString: { + page: '1', + installer: 'daisy' + } + }, + response: { + data: { + "pagination": { + "current_page": 1, + "total_pages": 1 + }, + "deployresults": [ + { + "build_id": 411, + "upstream_build_id": 184, + "scenario": "os-nosdn-nofeature-ha", + "stop_date": "2018-01-2723:21:31.3N", + "start_date": "2018-01-2723:21:28.3N", + "upstream_job_name": "daisy-os-nosdn-nofeature-ha-baremetal-daily-master", + "version": "master", + "pod_name": "zte-pod", + "criteria": "PASS", + "installer": "daisy", + "_id": "5a6dc1089a07c80f3c9f8d63", + "job_name": "daisy-deploy-baremetal-daily-master", + "details": null + } + ] + } + } + }, + { + request: { + path: '/api/v1/deployresults', + method: 'GET', + queryString: { + page: '1', + installer: 'daisy', + job_name : 'daisy-deploy-baremetal-daily-master' + } + }, + response: { + data: { + "pagination": { + "current_page": 1, + "total_pages": 1 + }, + "deployresults": [ + { + "build_id": 411, + "upstream_build_id": 184, + "scenario": "os-nosdn-nofeature-ha", + "stop_date": "2018-01-2723:21:31.3N", + "start_date": "2018-01-2723:21:28.3N", + "upstream_job_name": "daisy-os-nosdn-nofeature-ha-baremetal-daily-master", + "version": "master", + "pod_name": "zte-pod", + "criteria": "PASS", + "installer": "daisy", + "_id": "5a6dc1089a07c80f3c9f8d64", + "job_name": "daisy-deploy-baremetal-daily-master", + "details": null + } + ] + } + } + } + ]); + }); + + afterEach(function(){ + mock.teardown(); + }); + + it( 'should show the deploy results page for user', function() { + browser.get(baseURL+"#/deployresults"); + expect(element(by.cssContainingText(".ng-binding.ng-scope","Deploy Results")).isDisplayed()).toBe(true); + }); + + it( 'navigate user to results page', function() { + browser.get(baseURL); + var resultLink = element(by.linkText('Deploy Results')).click(); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/deployresults'), 10000); + }); + + it('Should show the results in results page for user ', function () { + browser.get(baseURL+"#/deployresults"); + var row = element.all(by.repeater('(index, result) in ctrl.data.deployresults')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("3c9f8d62"); + }); + + it('Should show the results in results page related to the filters for user ', function () { + browser.get(baseURL+"#/deployresults"); + var filter = element(by.model('ctrl.filter')); + var filterText = element(by.model('ctrl.filterText')); + filter.sendKeys('installer'); + filterText.sendKeys('daisy'); + var buttonFilter = element(by.buttonText('Filter')); + buttonFilter.click(); + var row = element.all(by.repeater('(index, result) in ctrl.data.deployresults')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("3c9f8d63"); + filter.sendKeys('job_name'); + filterText.sendKeys('daisy-deploy-baremetal-daily-master') + buttonFilter.click(); + expect(cells.get(0).getText()).toContain("3c9f8d64"); + }); + it('Should not show the results in results page related to the filters for user ', function () { + browser.get(baseURL+"#/deployresults"); + var filter = element(by.model('ctrl.filter')); + var filterText = element(by.model('ctrl.filterText')); + filter.sendKeys('installer'); + filterText.sendKeys('daisy1'); + var buttonFilter = element(by.buttonText('Filter')); + buttonFilter.click(); + expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope')) + .isDisplayed()).toBe(true); + }); + + it('Clear the filter', function () { + browser.get(baseURL+"#/deployresults"); + var filter = element(by.model('ctrl.filter')); + var filterText = element(by.model('ctrl.filterText')); + filter.sendKeys('installer'); + filterText.sendKeys('daisy'); + var buttonFilter = element(by.buttonText('Filter')); + buttonFilter.click(); + var row = element.all(by.repeater('(index, result) in ctrl.data.deployresults')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("3c9f8d63"); + var buttonClear = element(by.buttonText('Clear')); + buttonClear.click(); + var row = element.all(by.repeater('(index, result) in ctrl.data.deployresults')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("3c9f8d63"); + }); + + it('view the deploy results ', function () { + browser.get(baseURL+"#/deployresults"); + var viewOperation = element(by.linkText('3c9f8d62')) + viewOperation.click(); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains('#/deployresults/5a6dc1089a07c80f3c9f8d62'), 10000); + }); + +});
\ No newline at end of file diff --git a/testapi/opnfv_testapi/tests/UI/e2e/homeControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/homeControllerSpec.js new file mode 100644 index 0000000..013527d --- /dev/null +++ b/testapi/opnfv_testapi/tests/UI/e2e/homeControllerSpec.js @@ -0,0 +1,56 @@ +'use strict'; + +var mock = require('protractor-http-mock'); +var baseURL = "http://localhost:8000" +describe('testing the home page for anonymous user', function () { + + it( 'should navigate to pods link ', function() { + browser.get(baseURL); + var signOut = element(by.linkText('Sign In / Sign Up')) + expect(signOut.isDisplayed()).toBe(true); + }); +}); + +describe('testing the home page for user', function () { + beforeEach(function(){ + mock([{ + request: { + path: '/api/v1/pods', + method: 'GET' + }, + response: { + data: { + pods: [{role: "community-ci", name: "test", creator: "testUser", + details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed", + creation_date: "2017-10-25 11:58:25.926168"}] + } + } + }, + { + request: { + path: '/api/v1/profile', + method: 'GET' + }, + response: { + data: { + "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", + "user": "testUser", "groups": ["opnfv-testapi-users", + "opnfv-gerrit-functest-submitters"], "email": "testuser@test.com" + } + } + }]) + }); + + afterEach(function(){ + mock.teardown(); + }); + + it( 'should show the profile page', function() { + browser.get(baseURL); + var profile = element(by.linkText('Profile')) + expect(profile.isDisplayed()).toBe(true); + profile.click() + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '/#/profile'), 10000); + }); +});
\ No newline at end of file diff --git a/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js index c3961ab..ac1f954 100644 --- a/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js +++ b/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js @@ -4,202 +4,418 @@ var mock = require('protractor-http-mock'); var baseURL = "http://localhost:8000" describe('testing the Pods page for anonymous user', function () { - beforeEach(function(){ - mock([{ - request: { - path: '/api/v1/pods', - method: 'GET' - }, - response: { - data: { - pods: [{role: "community-ci", name: "test", owner: "testUser", - details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed", - creation_date: "2017-10-25 11:58:25.926168"}] - } - } - }]); - }); - - afterEach(function(){ - mock.teardown(); - }); - - it( 'should navigate to pods link ', function() { - browser.get(baseURL); - var podslink = element(by.linkText('Pods')).click(); - var EC = browser.ExpectedConditions; - browser.wait(EC.urlContains(baseURL+ '/#/pods'), 10000); - }); - - it('create button is not visible for anonymous user', function () { - browser.get(baseURL+'#/pods'); - var buttonCreate = element(by.buttonText('Create')); - expect(buttonCreate.isDisplayed()).toBeFalsy(); - }); - - it('filter button is visible for anonymous user', function () { - var buttonFilter = element(by.buttonText('Filter')); - expect(buttonFilter.isDisplayed()).toBe(true) - }); - - it('clear button is visible for anonymous user', function () { - var buttonClear = element(by.buttonText('Clear')); - expect(buttonClear.isDisplayed()).toBe(true) - }); - - it('Show results when click filter button', function () { - var buttonFilter = element(by.buttonText('Filter')); - buttonFilter.click(); - var pod = element(by.css('.show-pod')); - expect(pod.isPresent()).toBe(true); - }); - - it('Show results when click clear button', function () { - browser.get(baseURL+'#/pods'); - var buttonClear = element(by.buttonText('Clear')); - buttonClear.click(); - var pod = element(by.css('.show-pod')); - expect(pod.isPresent()).toBe(true); - }); - - it('If details is not shown then show details when click the link',function() { - expect(element(by.css('.show-pod.hidden')).isPresent()).toBe(true); - var podslink = element(by.linkText('test')).click(); - expect(element(by.css('.show-pod.hidden')).isPresent()).toBe(false); - }); - - it('If details is shown then hide details when click the link',function() { - expect(element(by.css('.show-pod.hidden')).isPresent()).toBe(false); - var podslink = element(by.linkText('test')).click(); - expect(element(by.css('.show-pod.hidden')).isPresent()).toBe(true); - }); - - it('If backend is not responding then show error when click filter button', function () { - browser.get(baseURL + '/#/pods'); - mock.teardown(); - var buttonFilter = element(by.buttonText('Filter')); - buttonFilter.click().then(function(){ - expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope')) - .isDisplayed()).toBe(true); - }); - }); + beforeEach(function(){ + mock([ + { + request: { + path: '/api/v1/pods', + method: 'GET', + queryString: { + name: 'test' + } + }, + response: { + data: { + pods: [{role: "community-ci", name: "test", creator: "testUser", + details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed", + creation_date: "2017-10-25 11:58:25.926168"}] + } + } + }, + { + request: { + path: '/api/v1/pods', + method: 'GET' + }, + response: { + data: { + pods: [ + {role: "community-ci", name: "test2", creator: "testUser", + details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7ae5", + creation_date: "2017-10-25 11:58:25.926168"}, + {role: "production-ci", name: "test", creator: "testUser", + details: "DemoDetails", mode: "virtual", _id: "59f02f099a07c84bfc5c7aed", + creation_date: "2017-10-25 11:58:25.926168"} + ] + } + } + } + ]); + }); + + afterEach(function(){ + mock.teardown(); + }); + + it( 'should navigate to pods link ', function() { + browser.get(baseURL); + var podslink = element(by.linkText('Pods')).click(); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '/#/pods'), 10000); + }); + + it('create button is not visible for anonymous user', function () { + browser.get(baseURL+'#/pods'); + var buttonCreate = element(by.buttonText('Create')); + expect(buttonCreate.isDisplayed()).toBeFalsy(); + }); + + it('filter button is visible for anonymous user', function () { + var buttonFilter = element(by.buttonText('Filter')); + expect(buttonFilter.isDisplayed()).toBe(true) + }); + + it('Delete button is visible for anonymous user', function () { + var buttonDelete = element(by.buttonText('Delete')); + expect(buttonDelete.isDisplayed()).toBeFalsy(); + }); + + it('Show results in a sorted order', function () { + var row = element.all(by.repeater('(index, pod) in ctrl.data.pods')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("test"); + }); + + it('Sort the results by mode', function () { + browser.get(baseURL+'#/pods'); + var sortMode = element(by.xpath('//*[@id="ng-app"]/body/div/div[5]/div/table/thead/tr/th[4]/a[2]/span')) + sortMode.click(); + var row = element.all(by.repeater('(index, pod) in ctrl.data.pods')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("test2"); + }); + + it('Sort the results by role', function () { + browser.get(baseURL+'#/pods'); + var sortRole = element(by.xpath('//*[@id="ng-app"]/body/div/div[5]/div/table/thead/tr/th[3]/a[2]/span')) + sortRole.click(); + var row = element.all(by.repeater('(index, pod) in ctrl.data.pods')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("test2"); + }); + + it('Show relevant results to the filter', function () { + var filter = element(by.model('ctrl.filterText')); + filter.sendKeys('test'); + var buttonFilter = element(by.buttonText('Filter')); + var row = element.all(by.repeater('(index, pod) in ctrl.data.pods')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("test"); + }); + + it('delete Operation is not visible for user ', function () { + browser.get(baseURL+'#/pods'); + var deleteOperation = element(by.css('a[title=Delete]')); + expect(deleteOperation.isDisplayed()).toBeFalsy(); + }); + }); describe('testing the Pods page for authorized user', function () { - beforeEach(function(){ - mock([ - { - request: { - path: '/api/v1/pods', - method: 'POST' - }, - response: { - data: { - href: baseURL+"/api/v1/pods/test" - } - } - }, - { - request: { - path: '/api/v1/pods', - method: 'POST', - data: { - name: 'test1', - details : 'DemoDetails', - role : 'community-ci', - mode : 'metal' - } - }, - response: { - status : 403 - } - }, - { - request: { - path: '/api/v1/profile', - method: 'GET' - }, - response: { - data: { - "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", - "user": "testUser", "groups": ["opnfv-testapi-users", - "opnfv-gerrit-functest-submitters"], "email": "testuser@test.com" - } - } - } - ]); - }); - - afterEach(function(){ - mock.teardown(); - }); - - it('create button is visible for authorized user', function () { - browser.get(baseURL + '/#/pods'); - var buttonCreate = element(by.buttonText('Create')); - expect(buttonCreate.isDisplayed()).toBe(true); - }); - - it('Do not show error if input is acceptable', function () { - var name = element(by.model('ctrl.name')); - var details = element(by.model('ctrl.details')); - name.sendKeys('test'); - details.sendKeys('DemoDetails'); - var buttonCreate = element(by.buttonText('Create')); - buttonCreate.click().then(function(){ - expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope')) - .isDisplayed()).toBe(false); - }); - }); - - it('Show error when user click the create button with a empty name', function () { - browser.get(baseURL+ '/#/pods'); - var details = element(by.model('ctrl.details')); - details.sendKeys('DemoDetails'); - var buttonCreate = element(by.buttonText('Create')); - buttonCreate.click(); - expect(element(by.cssContainingText(".alert","Name is missing.")).isDisplayed()).toBe(true); - }); - - it('Show error when user click the create button with an already existing name', function () { - browser.get(baseURL+ '/#/pods'); - var name = element(by.model('ctrl.name')); - var details = element(by.model('ctrl.details')); - name.sendKeys('test1'); - details.sendKeys('DemoDetails'); - var buttonCreate = element(by.buttonText('Create')); - buttonCreate.click(); - expect(element(by.cssContainingText(".alert","Error creating the new pod from server: undefined")).isDisplayed()).toBe(true); - }); - - it('If backend is not responding then show error when user click the create button',function(){ - mock.teardown(); - mock([ - { - request: { - path: '/api/v1/profile', - method: 'GET' - }, - response: { - data: { - "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", - "user": "testUser", "groups": ["opnfv-testapi-users"], - "email": "testuser@test.com" - } - } - } - ]); - browser.get(baseURL+ '/#/pods'); - var name = element(by.model('ctrl.name')); - var details = element(by.model('ctrl.details')); - name.sendKeys('test'); - details.sendKeys('DemoDetails'); - var buttonCreate = element(by.buttonText('Create')); - buttonCreate.click().then(function(){ - expect(element(by.css('.alert.alert-danger.ng-binding')) - .isDisplayed()).toBe(true); - }); - }); + beforeEach(function(){ + mock([{ + request: { + path: '/api/v1/pods', + method: 'GET' + }, + response: { + data: { + pods: [{role: "community-ci", name: "test", creator: "testUser", + details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed", + creation_date: "2017-10-25 11:58:25.926168"}] + } + } + }, + { + request: { + path: '/api/v1/profile', + method: 'GET' + }, + response: { + data: { + "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", + "user": "testUser", "groups": ["opnfv-testapi-users", + "opnfv-gerrit-functest-submitters"], "email": "testuser@test.com" + } + } + }, + { + request: { + path: '/api/v1/pods', + method: 'GET', + queryString: { + name: 'test' + } + }, + response: { + data: { + pods: [{role: "community-ci", name: "test", creator: "testUser", + details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed", + creation_date: "2017-10-25 11:58:25.926168"}] + } + } + }, + { + request: { + path: '/api/v1/pods/test', + method: 'DELETE' + }, + response: { + data: { + href: baseURL+"/api/v1/pods/test" + } + } + }, + { + request: { + path: '/api/v1/pods/test1', + method: 'DELETE' + }, + response: { + data: { + href: baseURL+"/api/v1/pods/test1" + } + } + }, + { + request: { + path: '/api/v1/pods', + method: 'POST' + }, + response: { + data: { + href: baseURL+"/api/v1/pods/test1" + } + } + }, + { + request: { + path: '/api/v1/pods/test', + method: 'GET' + }, + response: { + data: {role: "community-ci", name: "test", creator: "testUser", + details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed", + creation_date: "2017-10-25 11:58:25.926168"} + } + } + ]); + }); + + afterEach(function(){ + mock.teardown(); + }); + + it( 'should navigate to pods link ', function() { + browser.get(baseURL); + var podslink = element(by.linkText('Pods')).click(); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '/#/pods'), 10000); + }); + + it('create button is not visible for user', function () { + browser.get(baseURL+'#/pods'); + var buttonCreate = element(by.buttonText('Create')); + expect(buttonCreate.isDisplayed()).toBe(true); + }); + + it('filter button is visible for user', function () { + var buttonFilter = element(by.buttonText('Filter')); + expect(buttonFilter.isDisplayed()).toBe(true) + }); + + it('Delete button is visible for user', function () { + var buttonDelete = element(by.buttonText('Delete')); + expect(buttonDelete.isDisplayed()).toBe(true) + }); + + it('Show results', function () { + var row = element.all(by.repeater('(index, pod) in ctrl.data.pods')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("test"); + }); + + it('Show relevant results to the filter', function () { + var filter = element(by.model('ctrl.filterText')); + filter.sendKeys('test'); + var buttonFilter = element(by.buttonText('Filter')); + var row = element.all(by.repeater('(index, pod) in ctrl.data.pods')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("test"); + }); + + it('delete Operation is visible for user ', function () { + browser.get(baseURL+'#/pods'); + var deleteOperation = element(by.css('a[title=Delete]')); + expect(deleteOperation.isDisplayed()).toBe(true); + }); + + it('Batch Delete the pods ', function () { + browser.get(baseURL+"#/pods"); + var checkBox = element(by.model('ctrl.checkBox[index]')); + checkBox.click(); + var buttonDelete = element(by.buttonText('Delete'));; + buttonDelete.click(); + expect(element(by.cssContainingText('label', "You are about to delete following pods : test")) + .isDisplayed()).toBe(true); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Delete Success")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('Delete the pods ', function () { + browser.get(baseURL+"#/pods"); + var deleteOperation = element(by.css('a[title=Delete]')); + deleteOperation.click(); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Delete Success")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('Create the pod', function () { + browser.get(baseURL+"#/pods"); + var buttonCreate = element(by.buttonText('Create')); + buttonCreate.click(); + var name = element(by.model('PodModalCtrl.pod.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + name.sendKeys('test1'); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Create Success")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('Showing error when creating with a empty name ', function () { + browser.get(baseURL+"#/pods"); + var buttonCreate = element(by.buttonText('Create')); + buttonCreate.click(); + var name = element(by.model('PodModalCtrl.pod.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click() + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".error.show","Name is missing.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('cancel the delete confimation modal of the pod ', function () { + browser.get(baseURL+"#/pods"); + var deleteOperation = element(by.css('a[title=Delete]')); + deleteOperation.click(); + var buttonCancel = element(by.buttonText('Cancel')); + buttonCancel.click(); + expect(buttonCancel.isPresent()).toBe(false); + }); + + it('Delete the pods which do not exist ', function () { + mock.teardown(); + mock([{ + request: { + path: '/api/v1/pods', + method: 'GET' + }, + response: { + data: { + pods: [{role: "community-ci", name: "test1", creator: "testUser", + details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed", + creation_date: "2017-10-25 11:58:25.926168"}] + } + } + }, + { + request: { + path: '/api/v1/profile', + method: 'GET' + }, + response: { + data: { + "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", + "user": "testUser", "groups": ["opnfv-testapi-users", + "opnfv-gerrit-functest-submitters"], "email": "testuser@test.com" + } + } + }, + { + request: { + path: '/api/v1/pods/test1', + method: 'DELETE' + }, + response: { + status : 403, + data : 'pods do not exist' + } + } + ]); + browser.get(baseURL+"#/pods"); + var deleteOperation = element(by.css('a[title=Delete]')); + deleteOperation.click(); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.css(".error.show")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('view the test case ', function () { + browser.get(baseURL+"#/pods"); + var viewOperation = element(by.linkText('test')); + viewOperation.click(); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains('#/pods/test'), 10000); + }); + + it('Show error if server is not responding', function () { + mock.teardown(); + mock([{ + request: { + path: '/api/v1/pods', + method: 'GET' + }, + response: { + status : 404 + } + }, + { + request: { + path: '/api/v1/profile', + method: 'GET' + }, + response: { + data: { + "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", + "user": "testUser", "groups": ["opnfv-testapi-users", + "opnfv-gerrit-functest-submitters"], "email": "testuser@test.com" + } + } + }, + ]); + browser.get(baseURL+"#/pods"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '/#/pods'), 5000); + browser.ignoreSynchronization = true; + expect(element(by.css(".error.show")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + });
\ No newline at end of file diff --git a/testapi/opnfv_testapi/tests/UI/e2e/projectControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/projectControllerSpec.js deleted file mode 100644 index 475e037..0000000 --- a/testapi/opnfv_testapi/tests/UI/e2e/projectControllerSpec.js +++ /dev/null @@ -1,354 +0,0 @@ -'use strict'; - -var mock = require('protractor-http-mock'); -var baseURL = "http://localhost:8000/#/" - -describe('testing the Project Link for anonymous user', function () { - beforeEach(function(){ - mock([ - { - request: { - path: '/api/v1/projects/testproject', - method: 'GET' - }, - response: { - data: { - "owner": "thuva4", - "_id": "5a0c022f9a07c846d3c2cc94", - "creation_date": "2017-11-15 14:30:31.200259", - "description": "dsfsd", - "name": "testproject" - } - } - } - ]); - }); - - afterEach(function(){ - mock.teardown(); - }); - - it( 'navigate to the project page', function() { - browser.get(baseURL+"projects/testproject"); - var EC = browser.ExpectedConditions; - browser.wait(EC.urlContains(baseURL+ 'projects/testproject'), 10000); - }); - - it('show the project details for anonymous user ', function(){ - var table = $$('.projects-table.ng-scope tr'); - var projectDetailsLable = ['Name','Description','Creation date'] - var projectDetails = ['testproject', 'dsfsd','2017-11-15 14:30:31.200259'] - table.each(function(row,index) { - var rowElems = row.$$('td'); - expect(rowElems.count()).toBe(2); - expect(rowElems.get(0).getText()).toMatch(projectDetailsLable[index]); - expect(rowElems.get(1).getText()).toMatch(projectDetails[index]); - }); - }); - - it('should not show the update & delete button', function(){ - var buttonUpdate = element(by.buttonText('Update Project')); - var buttonDelete = element(by.buttonText('Delete Project')); - expect(buttonUpdate.isDisplayed()).toBeFalsy(); - expect(buttonDelete.isDisplayed()).toBeFalsy(); - }); - -}); - - -describe('testing the Project Link for authorized user(not a submitter)', function () { - beforeEach(function(){ - mock([ - { - request: { - path: '/api/v1/projects/testproject', - method: 'GET' - }, - response: { - data: { - "owner": "thuva4", - "_id": "5a0c022f9a07c846d3c2cc94", - "creation_date": "2017-11-15 14:30:31.200259", - "description": "dsfsd", - "name": "testproject" - } - } - }, - { - request: { - path: '/api/v1/profile', - method: 'GET' - }, - response: { - data: { - "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", - "user": "testUser", "groups": ["opnfv-testapi-users"], - "email": "testuser@test.com" - } - } - } - ]); - }); - - afterEach(function(){ - mock.teardown(); - }); - - it( 'navigate to the project page', function() { - browser.get(baseURL+"projects/testproject"); - var EC = browser.ExpectedConditions; - browser.wait(EC.urlContains(baseURL+ 'projects/testproject'), 10000); - }); - - it('show the project details for user ', function(){ - var table = $$('.projects-table.ng-scope tr'); - var projectDetailsLable = ['Name','Description','Creation date'] - var projectDetails = ['testproject', 'dsfsd','2017-11-15 14:30:31.200259'] - table.each(function(row,index) { - var rowElems = row.$$('td'); - expect(rowElems.count()).toBe(2); - expect(rowElems.get(0).getText()).toMatch(projectDetailsLable[index]); - expect(rowElems.get(1).getText()).toMatch(projectDetails[index]); - }); - }); - - it('should not show the update & delete button', function(){ - var buttonUpdate = element(by.buttonText('Update Project')); - var buttonDelete = element(by.buttonText('Delete Project')); - expect(buttonUpdate.isDisplayed()).toBeFalsy(); - expect(buttonDelete.isDisplayed()).toBeFalsy(); - }); - -}); - -describe('testing the Project Link for authorized user(a submitter)', function () { - beforeEach(function(){ - mock([ - { - request: { - path: '/api/v1/projects/testproject', - method: 'GET' - }, - response: { - data: { - "owner": "thuva4", - "_id": "5a0c022f9a07c846d3c2cc94", - "creation_date": "2017-11-15 14:30:31.200259", - "description": "dsfsd", - "name": "testproject" - } - } - }, - { - request: { - path: '/api/v1/projects/testproject1', - method: 'GET' - }, - response: { - data: { - "owner": "thuva4", - "_id": "5a0c022f9a07c846d3c2cc94", - "creation_date": "2017-11-15 14:30:31.200259", - "description": "dsfsd", - "name": "testproject1" - } - } - }, - { - request: { - path: '/api/v1/projects', - method: 'GET' - }, - response: { - data: { - "projects": [ - { - "owner": "thuva4", - "_id": "5a0c022f9a07c846d3c2cc94", - "creation_date": "2017-11-15 14:30:31.200259", - "description": "dsfsd", - "name": "testproject" - } - ] - } - } - }, - { - request: { - path: '/api/v1/projects/testproject', - method: 'DELETE' - }, - response: { - status : 200 - } - }, - { - request: { - path: '/api/v1/projects/testproject1', - method: 'DELETE' - }, - response: { - status : 403 - } - }, - { - request: { - path: '/api/v1/projects/testproject', - method: 'PUT', - data: { - name: 'testProject2', - description : 'demoDescription', - } - }, - response: { - status : 200, - data : { - "owner": "thuva4", - "_id": "5a0c022f9a07c846d3c2cc94", - "creation_date": "2017-11-15 14:30:31.200259", - "description": "dsfsd", - "name": "testproject2" - } - } - }, - { - request: { - path: '/api/v1/projects/testproject', - method: 'PUT', - data: { - name: 'testProject1', - description : 'demoDescription', - } - }, - response: { - status : 403 - } - }, - { - request: { - path: '/api/v1/profile', - method: 'GET' - }, - response: { - data: { - "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", - "user": "testUser", "groups": ["opnfv-testapi-users", - "opnfv-gerrit-testProject-submitters", - "opnfv-gerrit-testProject2-submitters" ], - "email": "testuser@test.com" - } - } - }, - ]); - }); - - afterEach(function(){ - mock.teardown(); - }); - - it( 'navigate to the project page', function() { - browser.get(baseURL+"projects/testproject"); - var EC = browser.ExpectedConditions; - browser.wait(EC.urlContains(baseURL+ 'projects/testproject'), 10000); - }); - - it('show the project details for user ', function(){ - var table = $$('.projects-table.ng-scope tr'); - var projectDetailsLable = ['Name','Description','Creation date'] - var projectDetails = ['testproject', 'dsfsd','2017-11-15 14:30:31.200259'] - table.each(function(row,index) { - var rowElems = row.$$('td'); - expect(rowElems.count()).toBe(2); - expect(rowElems.get(0).getText()).toMatch(projectDetailsLable[index]); - expect(rowElems.get(1).getText()).toMatch(projectDetails[index]); - }); - }); - - it('should show the update & delete button', function(){ - var buttonUpdate = element(by.buttonText('Update Project')); - var buttonDelete = element(by.buttonText('Delete Project')); - expect(buttonUpdate.isDisplayed()).toBe(true); - expect(buttonDelete.isDisplayed()).toBe(true); - }); - - it('show the update modal when user clicks the update button', function(){ - browser.get(baseURL+"projects/testproject"); - var buttonDelete = element(by.buttonText('Update Project')).click(); - var EC = protractor.ExpectedConditions; - var elm = element(by.css(".modal-body")); - browser.wait(EC.textToBePresentInElement(elm, "Update"), 5000); - expect(elm.isDisplayed()).toBe(true); - var buttonCancel = element(by.buttonText('Cancel')).click(); - expect(elm.isPresent()).toEqual(false); - }); - - it('send a update request to server and show success when we click ok', function(){ - browser.get(baseURL+"projects/testproject"); - var buttonUpdate = element(by.buttonText('Update Project')).click(); - var EC = protractor.ExpectedConditions; - var elm = element(by.css(".modal-body")); - browser.wait(EC.textToBePresentInElement(elm, "Update"), 5000); - expect(elm.isDisplayed()).toBe(true); - var name = element(by.model('updateModal.name')); - var description = element(by.model('updateModal.description')); - name.click().clear().sendKeys('testProject2'); - description.click().clear().sendKeys('demoDescription'); - var buttonOk = element(by.buttonText('Ok')).click(); - expect(element(by.cssContainingText(".alert.alert-success", - "Update Success")) - .isDisplayed()).toBe(true); - }); - - it('show error when server send a error response when we click ok', function(){ - browser.get(baseURL+"projects/testproject"); - var buttonUpdate = element(by.buttonText('Update Project')).click(); - var EC = protractor.ExpectedConditions; - var elm = element(by.css(".modal-body")); - browser.wait(EC.textToBePresentInElement(elm, "Update"), 5000); - expect(elm.isDisplayed()).toBe(true); - var name = element(by.model('updateModal.name')); - var description = element(by.model('updateModal.description')); - name.click().clear().sendKeys('testProject1'); - description.click().clear().sendKeys('demoDescription'); - var buttonOk = element(by.buttonText('Ok')).click(); - expect(element(by.cssContainingText(".alert", - "Error updating the existing Project from server: undefined")) - .isDisplayed()).toBe(true); - }); - - it('show the confirm modal when user clicks the delete button', function(){ - var buttonDelete = element(by.buttonText('Delete Project')).click(); - var EC = protractor.ExpectedConditions; - var elm = element(by.css(".modal-body")); - browser.wait(EC.textToBePresentInElement(elm, "You are about to delete."), 5000); - expect(elm.isDisplayed()).toBe(true); - var buttonCancel = element(by.buttonText('Cancel')).click(); - expect(elm.isPresent()).toEqual(false); - }); - - it('send a delete request to server when we click ok', function(){ - var buttonDelete = element(by.buttonText('Delete Project')).click(); - var EC = protractor.ExpectedConditions; - var elm = element(by.css(".modal-body")); - browser.wait(EC.textToBePresentInElement(elm, "You are about to delete."), 5000); - expect(elm.isDisplayed()).toBe(true); - var buttonCancel = element(by.buttonText('Ok')).click(); - browser.wait(EC.urlContains(baseURL+ 'projects'), 10000); - }); - - it('show the error message when we click ok', function(){ - browser.get(baseURL+"projects/testproject1"); - var buttonDelete = element(by.buttonText('Delete Project')).click(); - var EC = protractor.ExpectedConditions; - var elm = element(by.css(".modal-body")); - browser.wait(EC.textToBePresentInElement(elm, "You are about to delete."), 5000); - expect(elm.isDisplayed()).toBe(true); - var buttonCancel = element(by.buttonText('Ok')).click(); - // browser.wait(EC.urlContains(baseURL+ 'projects'), 10000); - expect(element(by.cssContainingText(".alert", - "Error deleting project from server: undefined")) - .isDisplayed()).toBe(true); - // browser.pause(); - }); - -});
\ No newline at end of file diff --git a/testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js index 64a5aeb..da86389 100644 --- a/testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js +++ b/testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js @@ -15,7 +15,7 @@ describe('testing the Projects Link for anonymous user', function () { data: { "projects": [ { - "owner": "thuva4", + "creator": "thuva4", "_id": "5a0c022f9a07c846d3c2cc94", "creation_date": "2017-11-15 14:30:31.200259", "description": "dsfsd", @@ -28,13 +28,13 @@ describe('testing the Projects Link for anonymous user', function () { ]); }); - afterEach(function(){ - mock.teardown(); - }); + afterEach(function(){ + mock.teardown(); + }); - it( 'should show the Projects Link for anonymous user', function() { + it( 'should show the Projects Link for anonymous user', function() { mock.teardown(); - browser.get(baseURL); + browser.get(baseURL); var projectslink = element(by.linkText('Projects')); expect(projectslink.isPresent()).toBe(true); }); @@ -51,16 +51,22 @@ describe('testing the Projects Link for anonymous user', function () { expect(buttonCreate.isDisplayed()).toBeFalsy(); }); - it('Show projects list when user comes to the projects page', function () { - var firstBookName = element(by.repeater('(index, project) in ctrl.data.projects'). - row(0).column('{{project.name}}')); - expect(firstBookName).toBeDefined(); + it('Delete button is not visible for anonymous user ', function () { + browser.get(baseURL+'#/projects'); + var buttonCreate = element(by.buttonText('Create')); + expect(buttonCreate.isDisplayed()).toBeFalsy(); }); - it('redirect to project page when user clicks a project',function(){ - var projectlink = element(by.linkText('testproject')).click(); - var EC = browser.ExpectedConditions; - browser.wait(EC.urlContains(baseURL+ '/#/projects/testproject'), 10000); + it('Show projects list when anonymous user comes to the projects page', function () { + var row = element.all(by.repeater('(index, project) in ctrl.data.projects')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("testproject"); + }); + + it('delete Operation is not visible for anonymous user ', function () { + browser.get(baseURL+'#/projects'); + var deleteOperation = element(by.css('a[title=Delete]')); + expect(deleteOperation.isDisplayed()).toBeFalsy(); }); }); @@ -70,6 +76,26 @@ describe('testing the Project Link for user who is not in submitter group', func mock([ { request: { + path: '/api/v1/projects', + method: 'GET', + queryString: { + name: 'test' + } + }, + response: { + data: { + "projects": [ + { + "_id": "5a0c1c9a9a07c846d3a7247b", + "creation_date": "2017-11-15 16:23:14.217093", + "description": "sdgfd", + "name": "test" + }] + } + } + }, + { + request: { path: '/api/v1/profile', method: 'GET' }, @@ -80,13 +106,32 @@ describe('testing the Project Link for user who is not in submitter group', func "email": "testuser@test.com" } } + }, + { + request: { + path: '/api/v1/projects', + method: 'GET' + }, + response: { + data: { + "projects": [ + { + "creator": "thuva4", + "_id": "5a0c022f9a07c846d3c2cc94", + "creation_date": "2017-11-15 14:30:31.200259", + "description": "dsfsd", + "name": "testproject" + } + ] + } + } } ]); }); afterEach(function(){ - mock.teardown(); - }); + mock.teardown(); + }); it( 'should show the Project Link for user', function() { browser.get(baseURL); @@ -106,6 +151,28 @@ describe('testing the Project Link for user who is not in submitter group', func var buttonCreate = element(by.buttonText('Create')); expect(buttonCreate.isDisplayed()).toBeFalsy(); }); + + it('Delete button is not visible for user ', function () { + browser.get(baseURL+'#/projects'); + var buttonDelete = element(by.buttonText('Delete')); + expect(buttonDelete.isDisplayed()).toBeFalsy(); + }); + + it('delete Operation is not visible for user ', function () { + browser.get(baseURL+'#/projects'); + var deleteOperation = element(by.css('a[title=Delete]')); + expect(deleteOperation.isDisplayed()).toBeFalsy(); + }); + + it('Show relevant results to the filter', function () { + var filter = element(by.model('ctrl.filterText')); + filter.sendKeys('test'); + var buttonFilter = element(by.buttonText('Filter')); + buttonFilter.click() + var row = element.all(by.repeater('(index, project) in ctrl.data.projects')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("test"); + }); }) describe('testing the Project Link for user who is in submitter group', function () { @@ -139,6 +206,28 @@ describe('testing the Project Link for user who is in submitter group', function }, { request: { + path: '/api/v1/projects/vsfv', + method: 'DELETE' + }, + response: { + data: { + href: baseURL+"/api/v1/projects/testProject1" + } + } + }, + { + request: { + path: '/api/v1/projects/vsfv', + method: 'PUT' + }, + response: { + data: { + href: baseURL+"/api/v1/projects/testProject1" + } + } + }, + { + request: { path: '/api/v1/projects', method: 'POST', data: { @@ -163,13 +252,30 @@ describe('testing the Project Link for user who is in submitter group', function status : 403, data : 'You do not have permission to perform this action' } + }, + { + request: { + path: '/api/v1/projects', + method: 'GET' + }, + response: { + data : { + "projects": [ + { + "_id": "5a0c1c9a9a07c846d3a7247b", + "creation_date": "2017-11-15 16:23:14.217093", + "description": "sdgfd", + "name": "vsfv" + }] + } + } } ]); }); afterEach(function(){ - mock.teardown(); - }); + mock.teardown(); + }); it( 'should show the Project Link for user', function() { browser.get(baseURL); @@ -190,58 +296,121 @@ describe('testing the Project Link for user who is in submitter group', function expect(buttonCreate.isDisplayed()).toBe(true); }); - it('Show error when user click the create button with a empty name', function () { - browser.get(baseURL+ '/#/projects'); - var description = element(by.model('ctrl.description')); - description.sendKeys('DemoDescription'); - var buttonCreate = element(by.buttonText('Create')); - buttonCreate.click(); - expect(element(by.cssContainingText(".alert","Name is missing.")) + it('Delete button is visible for user ', function () { + browser.get(baseURL+'#/projects'); + var buttonDelete = element(by.buttonText('Delete')); + expect(buttonDelete.isDisplayed()).toBe(true); + }); + + it('delete Operation is visible for user ', function () { + browser.get(baseURL+'#/projects'); + var deleteOperation = element(by.css('a[title=Delete]')); + expect(deleteOperation.isDisplayed()).toBe(true); + }); + + it('Edit Operation is visible for user ', function () { + browser.get(baseURL+'#/projects'); + var editOperation = element(by.css('a[title=Edit]')); + expect(editOperation.isDisplayed()).toBe(true); + }); + + it('Create the Project', function () { + browser.get(baseURL+"#/projects"); + var buttonCreate = element(by.buttonText('Create')); + buttonCreate.click(); + var name = element(by.model('ProjectModalCtrl.project.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + name.sendKeys('testproject'); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Project is successfully created.")) .isDisplayed()).toBe(true); - }); - - it('Show error when user click the create button with an already existing name', function () { - browser.get(baseURL+ '/#/projects'); - var name = element(by.model('ctrl.name')); - var details = element(by.model('ctrl.description')); - name.sendKeys('testProject2'); - details.sendKeys('demoDescription'); - var buttonCreate = element(by.buttonText('Create')); - buttonCreate.click(); - expect(element(by.cssContainingText(".alert", - "Error creating the new Project from server:undefined")) + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('Show error if user doesnt have permission to Create the Project', function () { + browser.get(baseURL+"#/projects"); + var buttonCreate = element(by.buttonText('Create')); + buttonCreate.click(); + var name = element(by.model('ProjectModalCtrl.project.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + var description = element(by.model('ProjectModalCtrl.project.description')); + name.sendKeys('testProject2'); + description.sendKeys('demoDescription'); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.css(".error")).isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('Showing error when creating with a empty name ', function () { + browser.get(baseURL+"#/projects"); + var buttonCreate = element(by.buttonText('Create')); + buttonCreate.click(); + var name = element(by.model('ProjectModalCtrl.project.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".alert","Name is missing.")) .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; }); - it('Show error when user try to create a project which he is not belonged to ', function () { - browser.get(baseURL+ '/#/projects'); - var name = element(by.model('ctrl.name')); - var details = element(by.model('ctrl.description')); - name.sendKeys('testProject3'); - details.sendKeys('demoDescription'); - var buttonCreate = element(by.buttonText('Create')); + it('Show error when user click the create button with an already existing name', function () { + browser.get(baseURL+"#/projects"); + var buttonCreate = element(by.buttonText('Create')); buttonCreate.click(); - expect(element(by.cssContainingText(".alert", - 'Error creating the new Project from server:"You do not have permission to perform this action"')).isDisplayed()) - .toBe(true); + var name = element(by.model('ProjectModalCtrl.project.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + var description = element(by.model('ProjectModalCtrl.project.description')); + name.sendKeys('testProject3'); + description.sendKeys('demoDescription'); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.css(".error")).isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('cancel the delete confimation modal of the project ', function () { + browser.get(baseURL+"#/projects"); + var deleteOperation = element(by.css('a[title=Delete]')); + deleteOperation.click(); + var buttonCancel = element(by.buttonText('Cancel')); + buttonCancel.click(); + expect(buttonCancel.isPresent()).toBe(false); }); - it('Do not show error if input is acceptable', function () { - var name = element(by.model('ctrl.name')); - var details = element(by.model('ctrl.description')); - name.sendKeys('testProject1'); - details.sendKeys('demoDescription'); - var buttonCreate = element(by.buttonText('Create')); - buttonCreate.click().then(function(){ - expect(element(by.cssContainingText(".alert", - "Create Success")) - .isDisplayed()).toBe(true); - }); + it('Delete the projects ', function () { + browser.get(baseURL+"#/projects"); + var deleteOperation = element(by.css('a[title=Delete]')); + deleteOperation.click(); + expect(element(by.cssContainingText('label', "You are about to delete following projects : vsfv")) + .isDisplayed()).toBe(true); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Projects is successfully deleted")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; }); - it('If backend is not responding then show error when user click the create button',function(){ - mock.teardown(); - mock([ + it(' Show error if user doesnt has permission to delete the projects ', function () { + mock.teardown(); + mock([ { request: { path: '/api/v1/profile', @@ -256,16 +425,185 @@ describe('testing the Project Link for user who is in submitter group', function "email": "testuser@test.com" } } + }, + { + request: { + path: '/api/v1/projects/testproject3', + method: 'DELETE' + }, + response: { + status: 403 + } + }, + { + request: { + path: '/api/v1/projects', + method: 'GET' + }, + response: { + data : { + "projects": [ + { + "_id": "5a0c1c9a9a07c846d3a7247b", + "creation_date": "2017-11-15 16:23:14.217093", + "description": "sdgfd", + "name": "testproject3" + }] + } + } } - ]); - browser.get(baseURL+ '/#/projects'); - var name = element(by.model('ctrl.name')); - var details = element(by.model('ctrl.description')); - name.sendKeys('testProject1'); - details.sendKeys('demoDescription'); - var buttonCreate = element(by.buttonText('Create')); - buttonCreate.click().then(function(){ - expect(element(by.css(".alert.alert-danger")).isDisplayed()).toBe(true); - }); - }); + ]); + browser.get(baseURL+"#/projects"); + var deleteOperation = element(by.css('a[title=Delete]')); + deleteOperation.click(); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.css(".error")).isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('cancel the Edit modal of the Project ', function () { + browser.get(baseURL+"#/projects"); + var editOperation = element(by.css('a[title=Edit]')); + editOperation.click(); + var name = element(by.model('ProjectModalCtrl.project.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + name.sendKeys('test1'); + var buttonCancel = element(by.buttonText('Cancel')); + buttonCancel.click(); + expect(name.isPresent()).toBe(false); + }); + + it('Edit the Project ', function () { + browser.get(baseURL+"#/projects"); + var editOperation = element(by.css('a[title=Edit]')); + editOperation.click(); + var name = element(by.model('ProjectModalCtrl.project.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + name.sendKeys('test1'); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click() + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Project is successfully updated.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + + }); + + it('Show error if user doesnt has permission to edit the projects ', function () { + mock.teardown(); + mock([ + { + request: { + path: '/api/v1/profile', + method: 'GET' + }, + response: { + data: { + "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", + "user": "testUser", "groups": ["opnfv-testapi-users", + "opnfv-gerrit-testProject1-submitters", + "opnfv-gerrit-testProject2-submitters" ], + "email": "testuser@test.com" + } + } + }, + { + request: { + path: '/api/v1/projects/testproject3', + method: 'PUT' + }, + response: { + status: 403 + } + }, + { + request: { + path: '/api/v1/projects', + method: 'GET' + }, + response: { + data : { + "projects": [ + { + "_id": "5a0c1c9a9a07c846d3a7247b", + "creation_date": "2017-11-15 16:23:14.217093", + "description": "sdgfd", + "name": "testproject3" + }] + } + } + } + ]); + browser.get(baseURL+"#/projects"); + var editOperation = element(by.css('a[title=Edit]')); + editOperation.click(); + var name = element(by.model('ProjectModalCtrl.project.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + name.sendKeys('test1'); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click() + browser.ignoreSynchronization = true; + expect(element(by.css(".error")).isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('Batch Delete the projects ', function () { + browser.get(baseURL+"#/projects"); + var checkBox = element(by.model('ctrl.checkBox[index]')); + checkBox.click(); + var buttonDelete = element(by.buttonText('Delete'));; + buttonDelete.click(); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Projects is successfully deleted")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + + }); + + it('If backend is not responding then show error when user click the create button',function(){ + mock.teardown(); + mock([ + { + request: { + path: '/api/v1/profile', + method: 'GET' + }, + response: { + data: { + "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", + "user": "testUser", "groups": ["opnfv-testapi-users", + "opnfv-gerrit-testProject1-submitters", + "opnfv-gerrit-testProject2-submitters" ], + "email": "testuser@test.com" + } + } + } + ]); + browser.get(baseURL+"#/projects"); + var buttonCreate = element(by.buttonText('Create')); + buttonCreate.click(); + var name = element(by.model('ProjectModalCtrl.project.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + var details = element(by.model('ProjectModalCtrl.project.description')); + name.sendKeys('testproject'); + details.sendKeys('demoDescription'); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click() + browser.ignoreSynchronization = true; + expect(element(by.css(".error")).isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); }) diff --git a/testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js index a14f8ea..48690a1 100644 --- a/testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js +++ b/testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js @@ -30,7 +30,6 @@ describe('testing the result page for anonymous user', function () { "user": null, "installer": "fuel", "scenario": "test-scenario", - "trust_indicator": null, "public": "true", "version": "euphrates", "details": "", @@ -45,11 +44,40 @@ describe('testing the result page for anonymous user', function () { }, { request: { + path: '/api/v1/results/5a45170bbb2092000e2643f4', + method: 'GET', + }, + response: { + data: { + "project_name": "testproject", + "description": "Demo results", + "stop_date": "2017-12-28 16:08:43", + "case_name": "testcase", + "build_tag": null, + "user": null, + "installer": "fuel", + "scenario": "test-scenario", + "public": "true", + "version": "euphrates", + "details": { + "failures": 0, + "errors": 0, + "stream": "steam text" + }, + "criteria": "PASS", + "_id": "5a45170bbb2092000e2643f4", + "start_date": "2017-12-28 14:44:27", + "pod_name": "testPod" + } + } + }, + { + request: { path: '/api/v1/results', method: 'GET', queryString: { page: '1', - project: 'testproject' + installer: 'testinstaller' } }, response: { @@ -66,7 +94,7 @@ describe('testing the result page for anonymous user', function () { "case_name": "testcase", "build_tag": null, "user": null, - "installer": "fuel", + "installer": "testinstaller", "scenario": "test-scenario", "trust_indicator": null, "public": "true", @@ -87,8 +115,8 @@ describe('testing the result page for anonymous user', function () { method: 'GET', queryString: { page: '1', - project: 'testproject', - case: 'testcase' + installer: 'testinstaller', + version: 'testversion' } }, response: { @@ -105,11 +133,10 @@ describe('testing the result page for anonymous user', function () { "case_name": "testcase", "build_tag": null, "user": null, - "installer": "fuel", + "installer": "testinstaller", "scenario": "test-scenario", - "trust_indicator": null, "public": "true", - "version": "euphrates", + "version": "testversion", "details": "", "criteria": "PASS", "_id": "5a45170bbb2092000e2643f6", @@ -119,7 +146,25 @@ describe('testing the result page for anonymous user', function () { ] } } - } + }, + { + request: { + path: '/api/v1/pods', + method: 'GET' + }, + response: { + data: { + pods: [ + {role: "community-ci", name: "test2", creator: "testUser", + details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7ae5", + creation_date: "2017-10-25 11:58:25.926168"}, + {role: "production-ci", name: "test", creator: "testUser", + details: "DemoDetails", mode: "virtual", _id: "59f02f099a07c84bfc5c7aed", + creation_date: "2017-10-25 11:58:25.926168"} + ] + } + } + } ]); }); @@ -127,47 +172,58 @@ describe('testing the result page for anonymous user', function () { mock.teardown(); }); - it( 'should show the results page for anonymous user', function() { + it( 'should show the results page ', function() { browser.get(baseURL+"#/results"); expect(element(by.cssContainingText(".ng-binding.ng-scope","Test Results")).isDisplayed()).toBe(true); }); - it( 'navigate anonymous user to testCase page', function() { + it( 'navigate anonymous user to results page', function() { browser.get(baseURL); var resultLink = element(by.linkText('Results')).click(); var EC = browser.ExpectedConditions; browser.wait(EC.urlContains(baseURL+ '#/results'), 10000); }); - it('Should show the results in results page for anonymous user ', function () { + it('Should show the results in results page', function () { browser.get(baseURL+"#/results"); var row = element.all(by.repeater('(index, result) in ctrl.data.results')).first(); var cells = row.all(by.tagName('td')); - expect(cells.get(0).getText()).toContain("5a45170bbb2092000e2643f4"); + expect(cells.get(0).getText()).toContain("0e2643f4"); + }); + + it( 'navigate to result page and check details', function() { + browser.get(baseURL); + var resultLink = element(by.linkText('Results')).click(); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/results'), 10000); + var resultLink = element(by.linkText('0e2643f4')).click(); + browser.wait(EC.urlContains(baseURL+ '#/result/5a45170bbb2092000e2643f4'), 10000); + expect(element(by.cssContainingText(".key.col-md-2","failures")).isDisplayed()).toBe(true); + expect(element(by.cssContainingText(".leaf-value.col-md-10","0")).isDisplayed()).toBe(true); }); - it('Should show the results in results page related to the filters for anonymous user ', function () { + it('Should show the results in results page related to the filters', function () { browser.get(baseURL+"#/results"); var filter = element(by.model('ctrl.filter')); var filterText = element(by.model('ctrl.filterText')); - filter.sendKeys('project'); - filterText.sendKeys('testproject'); + filter.sendKeys('installer'); + filterText.sendKeys('testinstaller'); var buttonFilter = element(by.buttonText('Filter')); buttonFilter.click(); var row = element.all(by.repeater('(index, result) in ctrl.data.results')).first(); var cells = row.all(by.tagName('td')); - expect(cells.get(0).getText()).toContain("5a45170bbb2092000e2643f5"); - filter.sendKeys('case'); - filterText.sendKeys('testcase') + expect(cells.get(0).getText()).toContain("0e2643f5"); + filter.sendKeys('version'); + filterText.sendKeys('testversion') buttonFilter.click(); - expect(cells.get(0).getText()).toContain("5a45170bbb2092000e2643f6"); + expect(cells.get(0).getText()).toContain("0e2643f6"); }); it('Should not show the results in results page related to the filters for anonymous user ', function () { browser.get(baseURL+"#/results"); var filter = element(by.model('ctrl.filter')); var filterText = element(by.model('ctrl.filterText')); - filter.sendKeys('project'); - filterText.sendKeys('testproject1'); + filter.sendKeys('installer'); + filterText.sendKeys('testisntaller1'); var buttonFilter = element(by.buttonText('Filter')); buttonFilter.click(); expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope')) @@ -235,7 +291,7 @@ describe('testing the result page for user', function () { method: 'GET', queryString: { page: '1', - project: 'testproject' + installer: 'testinstaller' } }, response: { @@ -252,9 +308,8 @@ describe('testing the result page for user', function () { "case_name": "testcase", "build_tag": null, "user": null, - "installer": "fuel", + "installer": "testinstaller", "scenario": "test-scenario", - "trust_indicator": null, "public": "true", "version": "euphrates", "details": "", @@ -273,8 +328,8 @@ describe('testing the result page for user', function () { method: 'GET', queryString: { page: '1', - project: 'testproject', - case: 'testcase' + installer: 'testinstaller', + version: 'testversion' } }, response: { @@ -291,11 +346,11 @@ describe('testing the result page for user', function () { "case_name": "testcase", "build_tag": null, "user": null, - "installer": "fuel", + "installer": "testinstaller", "scenario": "test-scenario", "trust_indicator": null, "public": "true", - "version": "euphrates", + "version": "testversion", "details": "", "criteria": "PASS", "_id": "5a45170bbb2092000e2643f6", @@ -305,7 +360,25 @@ describe('testing the result page for user', function () { ] } } - } + }, + { + request: { + path: '/api/v1/pods', + method: 'GET' + }, + response: { + data: { + pods: [ + {role: "community-ci", name: "test2", creator: "testUser", + details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7ae5", + creation_date: "2017-10-25 11:58:25.926168"}, + {role: "production-ci", name: "test", creator: "testUser", + details: "DemoDetails", mode: "virtual", _id: "59f02f099a07c84bfc5c7aed", + creation_date: "2017-10-25 11:58:25.926168"} + ] + } + } + } ]); }); @@ -329,31 +402,49 @@ describe('testing the result page for user', function () { browser.get(baseURL+"#/results"); var row = element.all(by.repeater('(index, result) in ctrl.data.results')).first(); var cells = row.all(by.tagName('td')); - expect(cells.get(0).getText()).toContain("5a45170bbb2092000e2643f4"); + expect(cells.get(0).getText()).toContain("0e2643f4"); }); it('Should show the results in results page related to the filters for user ', function () { browser.get(baseURL+"#/results"); var filter = element(by.model('ctrl.filter')); var filterText = element(by.model('ctrl.filterText')); - filter.sendKeys('project'); - filterText.sendKeys('testproject'); + filter.sendKeys('installer'); + filterText.sendKeys('testinstaller'); var buttonFilter = element(by.buttonText('Filter')); buttonFilter.click(); var row = element.all(by.repeater('(index, result) in ctrl.data.results')).first(); var cells = row.all(by.tagName('td')); - expect(cells.get(0).getText()).toContain("5a45170bbb2092000e2643f5"); - filter.sendKeys('case'); - filterText.sendKeys('testcase') + expect(cells.get(0).getText()).toContain("0e2643f5"); + filter.sendKeys('version'); + filterText.sendKeys('testversion') buttonFilter.click(); - expect(cells.get(0).getText()).toContain("5a45170bbb2092000e2643f6"); + expect(cells.get(0).getText()).toContain("0e2643f6"); + }); + + it('Clear the filter', function () { + browser.get(baseURL+"#/results"); + var filter = element(by.model('ctrl.filter')); + var filterText = element(by.model('ctrl.filterText')); + filter.sendKeys('installer'); + filterText.sendKeys('testinstaller'); + var buttonFilter = element(by.buttonText('Filter')); + buttonFilter.click(); + var row = element.all(by.repeater('(index, result) in ctrl.data.results')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("0e2643f5"); + var buttonClear = element(by.buttonText('Clear')); + buttonClear.click(); + var row = element.all(by.repeater('(index, result) in ctrl.data.results')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("0e2643f4"); }); it('Should not show the results in results page related to the filters for user ', function () { browser.get(baseURL+"#/results"); var filter = element(by.model('ctrl.filter')); var filterText = element(by.model('ctrl.filterText')); - filter.sendKeys('project'); - filterText.sendKeys('testproject1'); + filter.sendKeys('installer'); + filterText.sendKeys('testisntaller1'); var buttonFilter = element(by.buttonText('Filter')); buttonFilter.click(); expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope')) diff --git a/testapi/opnfv_testapi/tests/UI/e2e/scenarioControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/scenarioControllerSpec.js new file mode 100644 index 0000000..37b42dc --- /dev/null +++ b/testapi/opnfv_testapi/tests/UI/e2e/scenarioControllerSpec.js @@ -0,0 +1,1108 @@ +'use strict'; + +var mock = require('protractor-http-mock'); +var baseURL = "http://localhost:8000/" + +describe('testing the scenarios page for anonymous user', function () { + beforeEach(function(){ + mock([ + { + request: { + path: '/api/v1/scenarios', + method: 'GET' + }, + response: { + data: { + "scenarios": [ + { + "installers": [ + { + "installer": "fuel", + "versions": [ + { + "owner": "testUser", + "version": "colorado", + "projects": [ + { + "project": "yardstick", + "customs": [ + "dvs" + ], + "scores": [ + { + "date": "2016-12-11 01:45", + "score": "14/24" + }, + { + "date": "2016-12-15 05:28", + "score": "17/24" + }, + { + "date": "2016-12-17 03:41", + "score": "16/24" + }, + { + "date": "2018-01-22T18:30:00.000Z", + "score": "10/13" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + }, + { + "date": "2016-12-25 08:22", + "status": "gold" + }, + { + "date": "2018-01-22T18:30:00.000Z", + "status": "sf" + }, + { + "date": "2018-01-17T18:30:00.000Z", + "status": "df" + } + ] + }, + { + "project": "functest", + "customs": [ + "vping_ssh", + "vping_userdata", + ], + "scores": [ + { + "date": "2016-12-09 11:28", + "score": "6/8" + }, + { + "date": "2016-12-14 15:34", + "score": "8/8" + }, + { + "date": "2016-12-19 13:22", + "score": "8/8" + }, + { + "date": "2016-12-22 18:17", + "score": "8/8" + }, + { + "date": "2016-12-25 08:22", + "score": "8/8" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + } + ] + }, + { + "project": "sla", + "customs": [], + "scores": [ + { + "date": "2018-01-16T18:30:00.000Z", + "score": "sdS" + } + ], + "trust_indicators": [] + }, + { + "project": "dvsd", + "customs": [], + "scores": [], + "trust_indicators": [] + } + ] + }, + { + "owner": "dfgvds", + "version": "df", + "projects": [] + } + ] + }, + { + "installer": "fuel2", + "versions": [ + { + "owner": "testUser", + "version": "colorado", + "projects": [ + { + "project": "yardstick", + "customs": [ + "tc002", + "tc005", + "tc010", + "tc011" + ], + "scores": [ + { + "date": "2016-12-11 01:45", + "score": "14/24" + }, + { + "date": "2016-12-15 05:28", + "score": "17/24" + }, + { + "date": "2016-12-17 03:41", + "score": "16/24" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + }, + { + "date": "2016-12-25 08:22", + "status": "gold" + } + ] + }, + { + "project": "functest", + "customs": [ + "vping_ssh", + "vping_userdata" + ], + "scores": [ + { + "date": "2016-12-09 11:28", + "score": "6/8" + }, + { + "date": "2016-12-14 15:34", + "score": "8/8" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + } + ] + } + ] + } + ] + } + ], + "_id": "5a50fcacsdgdsgdasgfvb861c", + "name": "test-scenario", + "creation_date": "2018-01-06 22:13:24.160407" + } + ] + } + } + } + ]); + }); + + afterEach(function(){ + mock.teardown(); + }); + + it( 'should show the scenarios page for anonymous user', function() { + browser.get(baseURL+"#/scenarios"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios'), 10000); + var row = element.all(by.repeater('(index, scenario) in ctrl.data.scenarios')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("test-scenario"); + var scenarioLink = element(by.linkText('test-scenario')).click(); + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + }); + + it( 'should not show the add installer option for anonymous user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var buttonAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[2]/button')) + expect(buttonAdd.isDisplayed()).toBe(false); + }); + + it( 'Expand installers by anonymous user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a')) + installerShow.click(); + var row = element.all(by.repeater('(indexI, installer) in ctrl.data.scenarios[0].installers')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("fuel"); + }); + + it( 'should not show the delete installer option for anonymous user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a')) + installersShow.click(); + var installerDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[3]/button')) + expect(installerDelete.isDisplayed()).toBe(false); + }); + + it( 'Expand installer by anonymous user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + expect(versionsShow.isDisplayed()).toBe(true) + }); + + it( 'Expand versions by anonymous user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + expect(versionShow.isDisplayed()).toBe(true); + }); + + it( 'Expand version by anonymous user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + expect(projectsShow.isDisplayed()).toBe(true); + }); + + it( 'Expand projects by anonymous user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + expect(projectShow.isDisplayed()).toBe(true) + }); + + it( 'Expand project by anonymous user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + projectShow.click(); + var customsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[4]/td[2]/a/p')) + expect(customsShow.isDisplayed()).toBe(true) + var trustIndicatorsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/a/p')) + expect(trustIndicatorsShow.isDisplayed()).toBe(true) + var scoresShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/a/p')) + expect(scoresShow.isDisplayed()).toBe(true) + }); + +}); + + +describe('testing the scenarios page for user', function () { + beforeEach(function(){ + mock([ + { + request: { + path: '/api/v1/scenarios', + method: 'GET' + }, + response: { + data: { + "scenarios": [ + { + "installers": [ + { + "installer": "fuel", + "versions": [ + { + "owner": "testUser", + "version": "colorado", + "projects": [ + { + "project": "yardstick", + "customs": [ + "dvs" + ], + "scores": [ + { + "date": "2016-12-11 01:45", + "score": "14/24" + }, + { + "date": "2016-12-15 05:28", + "score": "17/24" + }, + { + "date": "2016-12-17 03:41", + "score": "16/24" + }, + { + "date": "2018-01-22T18:30:00.000Z", + "score": "10/13" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + }, + { + "date": "2016-12-25 08:22", + "status": "gold" + }, + { + "date": "2018-01-22T18:30:00.000Z", + "status": "sf" + }, + { + "date": "2018-01-17T18:30:00.000Z", + "status": "df" + } + ] + }, + { + "project": "functest", + "customs": [ + "vping_ssh", + "vping_userdata", + ], + "scores": [ + { + "date": "2016-12-09 11:28", + "score": "6/8" + }, + { + "date": "2016-12-14 15:34", + "score": "8/8" + }, + { + "date": "2016-12-19 13:22", + "score": "8/8" + }, + { + "date": "2016-12-22 18:17", + "score": "8/8" + }, + { + "date": "2016-12-25 08:22", + "score": "8/8" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + } + ] + }, + { + "project": "sla", + "customs": [], + "scores": [ + { + "date": "2018-01-16T18:30:00.000Z", + "score": "sdS" + } + ], + "trust_indicators": [] + }, + { + "project": "dvsd", + "customs": [], + "scores": [], + "trust_indicators": [] + } + ] + }, + { + "owner": "dfgvds", + "version": "df", + "projects": [] + } + ] + }, + { + "installer": "fuel2", + "versions": [ + { + "owner": "testUser", + "version": "colorado", + "projects": [ + { + "project": "yardstick", + "customs": [ + "tc002", + "tc005", + "tc010", + "tc011" + ], + "scores": [ + { + "date": "2016-12-11 01:45", + "score": "14/24" + }, + { + "date": "2016-12-15 05:28", + "score": "17/24" + }, + { + "date": "2016-12-17 03:41", + "score": "16/24" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + }, + { + "date": "2016-12-25 08:22", + "status": "gold" + } + ] + }, + { + "project": "functest", + "customs": [ + "vping_ssh", + "vping_userdata" + ], + "scores": [ + { + "date": "2016-12-09 11:28", + "score": "6/8" + }, + { + "date": "2016-12-14 15:34", + "score": "8/8" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + } + ] + } + ] + } + ] + } + ], + "_id": "5a50fcacsdgdsgdasgfvb861c", + "name": "test-scenario", + "creation_date": "2018-01-06 22:13:24.160407" + } + ] + } + } + }, + { + request: { + path: '/api/v1/profile', + method: 'GET' + }, + response: { + data: { + "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", + "user": "testUser", "groups": ["opnfv-testapi-users"], + "email": "testuser@test.com" + } + } + }, + { + request: { + path: '/api/v1/scenarios/test-scenario/installers', + method: 'POST' + }, + response: { + status : 200 + } + }, + { + request: { + path: '/api/v1/scenarios/test-scenario/installers', + method: 'DELETE' + }, + response: { + status : 200 + } + }, + { + request: { + path: '/api/v1/scenarios/test-scenario/versions', + method: 'POST', + queryString: { + installer: 'fuel' + } + }, + response: { + status : 200 + } + }, + { + request: { + path: '/api/v1/scenarios/test-scenario/versions', + method: 'DELETE', + queryString: { + installer: 'fuel' + } + }, + response: { + status : 200 + } + }, + { + request: { + path: '/api/v1/scenarios/test-scenario/projects', + method: 'POST', + queryString: { + installer: 'fuel', + version: 'colorado' + } + }, + response: { + status : 200 + } + }, + { + request: { + path: '/api/v1/scenarios/test-scenario/projects', + method: 'DELETE', + queryString: { + installer: 'fuel', + version: 'colorado' + } + }, + response: { + status : 200 + } + }, + { + request: { + path: '/api/v1/scenarios/test-scenario/customs', + method: 'POST', + queryString: { + installer: 'fuel', + version: 'colorado', + project: 'yardstick' + } + }, + response: { + status : 200 + } + }, + { + request: { + path: '/api/v1/scenarios/test-scenario/customs', + method: 'DELETE', + queryString: { + installer: 'fuel', + version: 'colorado', + project: 'yardstick' + } + }, + response: { + status : 200 + } + } + ]); + }); + + afterEach(function(){ + mock.teardown(); + }); + + it( 'should show the scenarios page for user', function() { + browser.get(baseURL+"#/scenarios"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios'), 10000); + var row = element.all(by.repeater('(index, scenario) in ctrl.data.scenarios')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("test-scenario"); + var scenarioLink = element(by.linkText('test-scenario')).click(); + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + }); + + it( 'should show the add installer option for user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var buttonAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[2]/button')) + expect(buttonAdd.isDisplayed()).toBe(true); + }); + + it('add installer', function(){ + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var buttonAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[2]/button')) + buttonAdd.click(); + var name = element(by.model('installerModalCtrl.installer.installer')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + name.sendKeys('test'); + var buttonOk = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[2]/button[1]')) + buttonOk.click() + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Installers are successfully updated.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + + }); + + it( 'Expand installers by user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installerShow.click(); + var row = element.all(by.repeater('(indexI, installer) in ctrl.data.scenarios[0].installers')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("fuel"); + }); + + it( 'should show the delete installer option for user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[3]/button')) + expect(installerDelete.isDisplayed()).toBe(true); + }); + + it( 'delete installer', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[3]/button')) + installerDelete.click() + expect(element(by.cssContainingText('label', "You are about to delete following installers : fuel")) + .isDisplayed()).toBe(true); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Installer is successfully deleted.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it( 'Expand installer by user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + expect(versionsShow.isDisplayed()).toBe(true) + }); + + it( 'add version for an installer', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[2]/button')) + versionAdd.click() + var version = element(by.model('versionModalCtrl.version.version')); + browser.wait(EC.visibilityOf(version), 5000); + version.sendKeys('testV'); + var owner = element(by.model('versionModalCtrl.version.owner')); + owner.sendKeys('testOwner'); + var buttonOk = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[2]/button[1]')) + buttonOk.click() + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Versions are successfully updated.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it( 'Expand versions by user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + expect(versionShow.isDisplayed()).toBe(true); + var installerAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[2]/button')) + var installerDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[3]/button')) + expect(installerAdd.isDisplayed()).toBe(false); + expect(installerDelete.isDisplayed()).toBe(false) + }); + + it( 'delete version', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var versionDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody[1]/tr[1]/td[3]/button')) + versionDelete.click() + expect(element(by.cssContainingText('label', "You are about to delete following version : colorado")) + .isDisplayed()).toBe(true); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Versions are successfully deleted.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it( 'Expand version by user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + expect(projectsShow.isDisplayed()).toBe(true); + }); + + it( 'add project', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[2]/button')) + projectAdd.click() + var project = element(by.model('projectModalCtrl.project.project')); + browser.wait(EC.visibilityOf(project), 5000); + project.sendKeys('testP'); + var buttonOk = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[2]/button[1]')) + buttonOk.click() + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Projects are successfully updated.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it( 'Expand projects by user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + expect(projectShow.isDisplayed()).toBe(true) + var versionAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[2]/button')) + var versionDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[3]/button')) + expect(versionAdd.isDisplayed()).toBe(false) + expect(versionDelete.isDisplayed()).toBe(false) + }); + + it( 'delete project', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[1]/td[3]/button')) + projectDelete.click() + expect(element(by.cssContainingText('label', "You are about to delete following projects : yardstick")) + .isDisplayed()).toBe(true); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Projects are successfully Deleted.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it( 'Expand project by user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + projectShow.click(); + var customsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[4]/td[2]/a/p')) + expect(customsShow.isDisplayed()).toBe(true) + var trustIndicatorsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/a/p')) + expect(trustIndicatorsShow.isDisplayed()).toBe(true) + var scoresShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/a/p')) + expect(scoresShow.isDisplayed()).toBe(true) + }); + + it( 'Expand trust indicator by user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + projectShow.click(); + var trustIndicatorsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/a/p')) + trustIndicatorsShow.click(); + var row = element.all(by.repeater('(indexTI, trust_indicator) in project.trust_indicators')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("silver"); + }); + + it( 'Expand score by user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + projectShow.click(); + var scoresShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[3]/td[2]/a/p')) + scoresShow.click(); + var row = element.all(by.repeater('(indexSC, score) in project.scores')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("14/24"); + }); + + it( 'Expand Customs by user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + projectShow.click(); + var customsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/a/p')) + customsShow.click(); + var row = element.all(by.repeater('(indexCU, custom) in project.customs')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("dvs"); + var projectAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[2]/button')) + var projectDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[1]/td[3]/button')) + expect(projectDelete.isDisplayed()).toBe(false) + expect(projectAdd.isDisplayed()).toBe(false) + var buttonAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/button')) + var buttonDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/table/tbody/tr[1]/td[2]/button')) + expect(buttonAdd.isDisplayed()).toBe(true) + expect(buttonDelete.isDisplayed()).toBe(true) + }); + + it( 'Add Customs by user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + projectShow.click(); + var customsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/a/p')) + customsShow.click(); + var row = element.all(by.repeater('(indexCU, custom) in project.customs')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("dvs"); + var buttonAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/button')) + buttonAdd.click() + var custom = element(by.model('customModalCtrl.custom')); + browser.wait(EC.visibilityOf(custom), 5000); + custom.sendKeys('testC'); + var buttonOk = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[2]/button[1]')) + buttonOk.click() + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Customs are successfully updated.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it( 'Add multiple Customs by user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + projectShow.click(); + var customsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/a/p')) + customsShow.click(); + var row = element.all(by.repeater('(indexCU, custom) in project.customs')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("dvs"); + var buttonAdd = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/button')) + buttonAdd.click() + var custom = element(by.model('customModalCtrl.custom')); + browser.wait(EC.visibilityOf(custom), 5000); + custom.sendKeys('testC,testD,'); + var buttonOk = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[2]/button[1]')) + buttonOk.click() + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Customs are successfully updated.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it( 'Delete Customs by user', function() { + browser.get(baseURL+"#/scenarios/test-scenario"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + var installersShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[1]/a/p')) + installersShow.click(); + var installerShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + installerShow.click(); + var versionsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[1]/a/p')) + versionsShow.click(); + var versionShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + versionShow.click() + var projectsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[1]/a')) + projectsShow.click(); + var projectShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody/tr[1]/td[2]/a')) + projectShow.click(); + var customsShow = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/a/p')) + customsShow.click(); + var row = element.all(by.repeater('(indexCU, custom) in project.customs')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(0).getText()).toContain("dvs"); + var buttonDelete = element(by.xpath('//*[@id="ng-app"]/body/div/div[1]/div/table/tbody/tr[5]/td[2]/div[3]/div/table/tbody/tr[2]/td[2]/div[3]/div/table/tbody/tr[3]/td[2]/div[3]/div/table/tbody[1]/tr[4]/td[2]/table/tbody/tr[1]/td[2]/button')) + buttonDelete.click() + expect(element(by.cssContainingText('label', "You are about to delete following customs : dvs")) + .isDisplayed()).toBe(true); + var buttonOk = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div[3]/button[1]')) + buttonOk.click() + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Customs are successfully deleted.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + +});
\ No newline at end of file diff --git a/testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js new file mode 100644 index 0000000..55922ad --- /dev/null +++ b/testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js @@ -0,0 +1,500 @@ +'use strict'; + +var mock = require('protractor-http-mock'); +var baseURL = "http://localhost:8000/" + +describe('testing the scenarios page for anonymous user', function () { + beforeEach(function(){ + mock([ + { + request: { + path: '/api/v1/scenarios', + method: 'GET' + }, + response: { + data: { + "scenarios": [ + { + "installers": [ + { + "installer": "fuel", + "versions": [ + { + "owner": "testUser", + "version": "colorado", + "projects": [ + { + "project": "yardstick", + "customs": [ + "dvs" + ], + "scores": [ + { + "date": "2016-12-11 01:45", + "score": "14/24" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + } + ] + } + ] + } + ] + } + ], + "_id": "5a50fcacsdgdsgdasgfvb861c", + "name": "test-scenario", + "creation_date": "2018-01-06 22:13:24.160407" + }, + { + "installers": [ + { + "installer": "fuel", + "versions": [ + { + "owner": "testUser", + "version": "colorado", + "projects": [ + { + "project": "yardstick", + "customs": [ + "dvs" + ], + "scores": [ + { + "date": "2016-12-11 01:45", + "score": "14/24" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + } + ] + } + ] + } + ] + } + ], + "_id": "5a50fcacsdgdsgdasgfvb861d", + "name": "z-test-scenario", + "creation_date": "2018-01-06 22:13:24.160407" + } + ] + } + } + } + ]); + }); + + afterEach(function(){ + mock.teardown(); + }); + + it( 'should show the scenarios page for anonymous user', function() { + browser.get(baseURL+"#/scenarios"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios'), 10000); + }); + + it( 'navigate anonymous user to scenarios page', function() { + browser.get(baseURL); + var resultLink = element(by.linkText('Scenarios')).click(); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios'), 10000); + }); + + it('Should show the scenarios in scenarios page for anonymous user ', function () { + browser.get(baseURL+"#/scenarios"); + var row = element.all(by.repeater('(index, scenario) in ctrl.data.scenarios')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("test-scenario"); + }); + + it('Sort scenarios', function () { + browser.get(baseURL+"#/scenarios"); + var sort = element(by.xpath('//*[@id="ng-app"]/body/div/div[5]/div/table/thead/tr/th[2]/a[2]/span')) + sort.click(); + var row = element.all(by.repeater('(index, scenario) in ctrl.data.scenarios')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("z-test-scenario"); + }); + + it('create button is not visible for anonymous user ', function () { + browser.get(baseURL+'#/scenarios'); + var buttonCreate = element(by.buttonText('Create')); + expect(buttonCreate.isDisplayed()).toBeFalsy(); + }); + it('delete button is not visible for anonymous user ', function () { + browser.get(baseURL+'#/scenarios'); + var buttonCreate = element(by.buttonText('Delete')); + expect(buttonCreate.isDisplayed()).toBeFalsy(); + }); + +}); + +describe('testing the scenarios page for user', function () { + beforeEach(function(){ + mock([ + { + request: { + path: '/api/v1/scenarios', + method: 'GET' + }, + response: { + data: { + "scenarios": [ + { + "installers": [ + { + "installer": "fuel", + "versions": [ + { + "owner": "testUser", + "version": "colorado", + "projects": [ + { + "project": "yardstick", + "customs": [ + "dvs" + ], + "scores": [ + { + "date": "2016-12-11 01:45", + "score": "14/24" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + } + ] + } + ] + } + ] + } + ], + "_id": "5a50fcacsdgdsgdasgfvb861c", + "name": "test-scenario", + "creation_date": "2018-01-06 22:13:24.160407" + } + ] + } + } + }, + { + request: { + path: '/api/v1/profile', + method: 'GET' + }, + response: { + data: { + "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", + "user": "testUser", "groups": ["opnfv-testapi-users"], + "email": "testuser@test.com" + } + } + }, + { + request: { + path: '/api/v1/scenarios', + method: 'POST' + }, + response: { + data: { + href: baseURL+"/api/v1/scenarios/testScenario" + } + } + }, + { + request: { + path: '/api/v1/scenarios/test-scenario', + method: 'DELETE' + }, + response: { + data: { + href: baseURL+"/api/v1/scenarios/testScenario" + } + } + }, + { + request: { + path: '/api/v1/scenarios/test-scenario', + method: 'PUT' + }, + response: { + data: { + href: baseURL+"/api/v1/scenarios/testScenario" + } + } + } + ]); + }); + + afterEach(function(){ + mock.teardown(); + }); + + it( 'should show the scenarios page for user', function() { + browser.get(baseURL+"#/scenarios"); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios'), 10000); + }); + + it( 'navigate user to scenarios page', function() { + browser.get(baseURL); + var resultLink = element(by.linkText('Scenarios')).click(); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios'), 10000); + }); + + it('Should show the scenarios in scenarios page for user ', function () { + browser.get(baseURL+"#/scenarios"); + var row = element.all(by.repeater('(index, scenario) in ctrl.data.scenarios')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("test-scenario"); + }); + + it('create button is visible for user ', function () { + browser.get(baseURL+'#/scenarios'); + var buttonCreate = element(by.buttonText('Create')); + expect(buttonCreate.isDisplayed()).toBe(true); + }); + + it('delete button is visible for user ', function () { + browser.get(baseURL+'#/scenarios'); + var buttonDelete = element(by.buttonText('Delete')); + expect(buttonDelete.isDisplayed()).toBe(true); + }); + + it('craete scenarrio by user without installers ', function () { + browser.get(baseURL+'#/scenarios'); + var buttonCreate = element(by.buttonText('Create')).click(); + var name = element(by.model('scenarioModalController.scenario.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + name.sendKeys('test'); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Scenario is successfully created.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('create scenarrio by user with installers ', function () { + browser.get(baseURL+'#/scenarios'); + var buttonCreate = element(by.buttonText('Create')).click(); + var name = element(by.model('scenarioModalController.scenario.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + name.sendKeys('test'); + var buttonInstaller = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[1]/div[1]/fieldset/div/div/div[2]/div[2]/button')) + buttonInstaller.click(); + var installer = element(by.model('installerModalCtrl.installer.installer')); + browser.wait(EC.visibilityOf(installer), 5000); + installer.sendKeys('testI'); + var buttonOK = element(by.xpath('//*[@id="ng-app"]/body/div[4]/div/div/div/div[2]/button[1]')); + buttonOK.click(); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Scenario is successfully created.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('create scenarrio by user with installers with versions ', function () { + browser.get(baseURL+'#/scenarios'); + var buttonCreate = element(by.buttonText('Create')).click(); + var name = element(by.model('scenarioModalController.scenario.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + name.sendKeys('test'); + var buttonInstaller = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[1]/div[1]/fieldset/div/div/div[2]/div[2]/button')) + buttonInstaller.click(); + var installer = element(by.model('installerModalCtrl.installer.installer')); + browser.wait(EC.visibilityOf(installer), 5000); + installer.sendKeys('testI'); + var buttonVersion = element(by.xpath('//*[@id="ng-app"]/body/div[4]/div/div/div/div[1]/div[1]/fieldset/div/div/div[2]/div[2]/button')) + buttonVersion.click(); + var version = element(by.model('versionModalCtrl.version.version')); + browser.wait(EC.visibilityOf(version), 5000); + version.sendKeys('testV'); + var owner = element(by.model('versionModalCtrl.version.owner')); + owner.sendKeys('testOwner'); + var buttonOK = element(by.xpath('//*[@id="ng-app"]/body/div[5]/div/div/div/div[2]/button[1]')); + buttonOK.click(); + var buttonOK = element(by.xpath('//*[@id="ng-app"]/body/div[4]/div/div/div/div[2]/button[1]')); + buttonOK.click(); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Scenario is successfully created.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('create scenarrio by user with installers with versions with project', function () { + browser.get(baseURL+'#/scenarios'); + var buttonCreate = element(by.buttonText('Create')).click(); + var name = element(by.model('scenarioModalController.scenario.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + name.sendKeys('test'); + var buttonInstaller = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[1]/div[1]/fieldset/div/div/div[2]/div[2]/button')) + buttonInstaller.click(); + var installer = element(by.model('installerModalCtrl.installer.installer')); + browser.wait(EC.visibilityOf(installer), 5000); + installer.sendKeys('testI'); + var buttonVersion = element(by.xpath('//*[@id="ng-app"]/body/div[4]/div/div/div/div[1]/div[1]/fieldset/div/div/div[2]/div[2]/button')) + buttonVersion.click(); + var version = element(by.model('versionModalCtrl.version.version')); + browser.wait(EC.visibilityOf(version), 5000); + version.sendKeys('testV'); + var owner = element(by.model('versionModalCtrl.version.owner')); + owner.sendKeys('testOwner'); + var buttonProject = element(by.xpath('//*[@id="ng-app"]/body/div[5]/div/div/div/div[1]/div[1]/fieldset/div/div/div[3]/div[2]/button')) + buttonProject.click(); + var project = element(by.model('projectModalCtrl.project.project')); + browser.wait(EC.visibilityOf(project), 5000); + project.sendKeys('testP'); + var buttonOK = element(by.xpath('//*[@id="ng-app"]/body/div[6]/div/div/div/div[2]/button[1]')); + buttonOK.click(); + var buttonOK = element(by.xpath('//*[@id="ng-app"]/body/div[5]/div/div/div/div[2]/button[1]')); + buttonOK.click(); + var buttonOK = element(by.xpath('//*[@id="ng-app"]/body/div[4]/div/div/div/div[2]/button[1]')); + buttonOK.click(); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Scenario is successfully created.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('create scenarrio by user with installers with versions with project with custom', function () { + browser.get(baseURL+'#/scenarios'); + var buttonCreate = element(by.buttonText('Create')).click(); + var name = element(by.model('scenarioModalController.scenario.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + name.sendKeys('test'); + var buttonInstaller = element(by.xpath('//*[@id="ng-app"]/body/div[3]/div/div/div/div[1]/div[1]/fieldset/div/div/div[2]/div[2]/button')) + buttonInstaller.click(); + var installer = element(by.model('installerModalCtrl.installer.installer')); + browser.wait(EC.visibilityOf(installer), 5000); + installer.sendKeys('testI'); + var buttonVersion = element(by.xpath('//*[@id="ng-app"]/body/div[4]/div/div/div/div[1]/div[1]/fieldset/div/div/div[2]/div[2]/button')) + buttonVersion.click(); + var version = element(by.model('versionModalCtrl.version.version')); + browser.wait(EC.visibilityOf(version), 5000); + version.sendKeys('testV'); + var owner = element(by.model('versionModalCtrl.version.owner')); + owner.sendKeys('testOwner'); + var buttonProject = element(by.xpath('//*[@id="ng-app"]/body/div[5]/div/div/div/div[1]/div[1]/fieldset/div/div/div[3]/div[2]/button')) + buttonProject.click(); + var project = element(by.model('projectModalCtrl.project.project')); + browser.wait(EC.visibilityOf(project), 5000); + project.sendKeys('testP'); + var buttonCustom = element(by.xpath('//*[@id="ng-app"]/body/div[6]/div/div/div/div[1]/div[1]/fieldset/div/div/div[2]/div[2]/button')) + buttonCustom.click(); + var custom = element(by.model('customModalCtrl.custom')); + browser.wait(EC.visibilityOf(custom), 5000); + custom.sendKeys('testC'); + var buttonOK = element(by.xpath('//*[@id="ng-app"]/body/div[7]/div/div/div/div[2]/button[1]')); + buttonOK.click(); + var buttonOK = element(by.xpath('//*[@id="ng-app"]/body/div[6]/div/div/div/div[2]/button[1]')); + buttonOK.click(); + var buttonOK = element(by.xpath('//*[@id="ng-app"]/body/div[5]/div/div/div/div[2]/button[1]')); + buttonOK.click(); + var buttonOK = element(by.xpath('//*[@id="ng-app"]/body/div[4]/div/div/div/div[2]/button[1]')); + buttonOK.click(); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Scenario is successfully created.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('view scenarrio by user ', function () { + browser.get(baseURL+'#/scenarios'); + var scenarioLink = element(by.linkText('test-scenario')).click(); + var EC = browser.ExpectedConditions; + browser.wait(EC.urlContains(baseURL+ '#/scenarios/test-scenario'), 10000); + }); + + it('delete Operation is visible for user ', function () { + browser.get(baseURL+'#/scenarios'); + var deleteOperation = element(by.css('a[title=Delete]')); + expect(deleteOperation.isDisplayed()).toBe(true); + }); + + it('edit Operation is visible for user ', function () { + browser.get(baseURL+'#/scenarios'); + var deleteOperation = element(by.css('a[title=Edit]')); + expect(deleteOperation.isDisplayed()).toBe(true); + }); + + it('Delete the Scenario ', function () { + browser.get(baseURL+'#/scenarios'); + var deleteOperation = element(by.css('a[title=Delete]')); + deleteOperation.click(); + expect(element(by.cssContainingText('label', "You are about to delete following scenarios : test-scenario")) + .isDisplayed()).toBe(true); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Scenario is successfully deleted.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('Batch Delete the scenarios ', function () { + browser.get(baseURL+'#/scenarios'); + var checkBox = element(by.model('ctrl.checkBox[index]')); + checkBox.click(); + var buttonDelete = element(by.buttonText('Delete'));; + buttonDelete.click(); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click(); + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Scenario is successfully deleted.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + + it('Edit the scenarios ', function () { + browser.get(baseURL+'#/scenarios'); + var editOperation = element(by.css('a[title=Edit]')); + editOperation.click(); + var name = element(by.model('ScenarioNameUpdateCtrl.name')); + var EC = browser.ExpectedConditions; + browser.wait(EC.visibilityOf(name), 5000); + name.sendKeys('test2'); + var buttonOK = element(by.buttonText('Ok')); + buttonOK.click() + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Scenario is successfully Updated.")) + .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; + }); + +});
\ No newline at end of file diff --git a/testapi/opnfv_testapi/tests/UI/e2e/testCasesControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/testCasesControllerSpec.js index d509c57..38e0f24 100644 --- a/testapi/opnfv_testapi/tests/UI/e2e/testCasesControllerSpec.js +++ b/testapi/opnfv_testapi/tests/UI/e2e/testCasesControllerSpec.js @@ -15,7 +15,7 @@ describe('testing the testCases page for anonymous user', function () { data: { "projects": [ { - "owner": "thuva4", + "creator": "thuva4", "_id": "5a0c022f9a07c846d3c2cc94", "creation_date": "2017-11-15 14:30:31.200259", "description": "dsfsd", @@ -32,7 +32,7 @@ describe('testing the testCases page for anonymous user', function () { }, response: { data: { - "owner": "thuva4", + "creator": "thuva4", "_id": "5a0c022f9a07c846d3c2cc94", "creation_date": "2017-11-15 14:30:31.200259", "description": "dsfsd", @@ -182,7 +182,7 @@ describe('testing the testcaese page for user who is not in submitter group', fu data: { "projects": [ { - "owner": "thuva4", + "creator": "thuva4", "_id": "5a0c022f9a07c846d3c2cc94", "creation_date": "2017-11-15 14:30:31.200259", "description": "dsfsd", @@ -199,7 +199,7 @@ describe('testing the testcaese page for user who is not in submitter group', fu }, response: { data: { - "owner": "thuva4", + "creator": "thuva4", "_id": "5a0c022f9a07c846d3c2cc94", "creation_date": "2017-11-15 14:30:31.200259", "description": "dsfsd", @@ -397,7 +397,7 @@ describe('testing the test cases page for user who is in submitter group', funct data: { "projects": [ { - "owner": "thuva4", + "creator": "thuva4", "_id": "5a0c022f9a07c846d3c2cc94", "creation_date": "2017-11-15 14:30:31.200259", "description": "dsfsd", @@ -414,7 +414,7 @@ describe('testing the test cases page for user who is in submitter group', funct }, response: { data: { - "owner": "thuva4", + "creator": "thuva4", "_id": "5a0c022f9a07c846d3c2cc94", "creation_date": "2017-11-15 14:30:31.200259", "description": "dsfsd", @@ -550,8 +550,11 @@ describe('testing the test cases page for user who is in submitter group', funct name.sendKeys('test'); var buttonOK = element(by.buttonText('Ok')); buttonOK.click(); - expect(element(by.cssContainingText(".alert","Testcase is successfully created.")) + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Testcase is successfully created.")) .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; }); it('Showing error when creating with a empty name ', function () { @@ -565,8 +568,11 @@ describe('testing the test cases page for user who is in submitter group', funct browser.wait(EC.visibilityOf(name), 5000); var buttonOK = element(by.buttonText('Ok')); buttonOK.click(); - expect(element(by.cssContainingText(".alert","Name is missing.")) + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".error.show","Name is missing.")) .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; }); it('cancel the delete confimation modal of the test case ', function () { @@ -575,6 +581,8 @@ describe('testing the test cases page for user who is in submitter group', funct testCases.click(); var deleteOperation = element(by.css('a[title=Delete]')); deleteOperation.click(); + expect(element(by.cssContainingText('label', "You are about to delete following testcases : testCase")) + .isDisplayed()).toBe(true); var buttonCancel = element(by.buttonText('Cancel')); buttonCancel.click(); expect(buttonCancel.isPresent()).toBe(false); @@ -588,8 +596,11 @@ describe('testing the test cases page for user who is in submitter group', funct deleteOperation.click(); var buttonOK = element(by.buttonText('Ok')); buttonOK.click(); - expect(element(by.cssContainingText(".alert","Test case is successfully deleted")) + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Test case is successfully deleted")) .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; }); it('cancel the Edit modal of the test case ', function () { @@ -619,8 +630,11 @@ describe('testing the test cases page for user who is in submitter group', funct name.sendKeys('test1'); var buttonOK = element(by.buttonText('Ok')); buttonOK.click(); - expect(element(by.cssContainingText(".alert","Test case is successfully updated")) + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Test case is successfully updated")) .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; }); it('view the test case ', function () { @@ -644,7 +658,10 @@ describe('testing the test cases page for user who is in submitter group', funct buttonDelete.click(); var buttonOK = element(by.buttonText('Ok')); buttonOK.click(); - expect(element(by.cssContainingText(".alert","Test case is successfully deleted")) + browser.ignoreSynchronization = true; + expect(element(by.cssContainingText(".success.show","Test case is successfully deleted")) .isDisplayed()).toBe(true); + browser.sleep(500); + browser.ignoreSynchronization = false; }); }) diff --git a/testapi/opnfv_testapi/tests/unit/common/test_config.py b/testapi/opnfv_testapi/tests/unit/common/test_config.py index 6d160ce..8e4966f 100644 --- a/testapi/opnfv_testapi/tests/unit/common/test_config.py +++ b/testapi/opnfv_testapi/tests/unit/common/test_config.py @@ -11,7 +11,7 @@ def test_config_normal(mocker, config_normal): assert CONF.mongo_url == 'mongodb://127.0.0.1:27017/' assert CONF.mongo_dbname == 'test_results_collection' assert CONF.api_port == 8000 - assert CONF.api_debug is True + assert CONF.api_debug is False assert CONF.api_token_check is False assert CONF.api_authenticate is True assert CONF.ui_url == 'http://localhost:8000' diff --git a/testapi/opnfv_testapi/tests/unit/executor.py b/testapi/opnfv_testapi/tests/unit/executor.py index 743c076..7c8cb8a 100644 --- a/testapi/opnfv_testapi/tests/unit/executor.py +++ b/testapi/opnfv_testapi/tests/unit/executor.py @@ -18,9 +18,9 @@ O_get_secure_cookie = ( def thread_execute(method, *args, **kwargs): - with ThreadPoolExecutor(max_workers=2) as executor: - result = executor.submit(method, *args, **kwargs) - return result + with ThreadPoolExecutor(max_workers=2) as executor: + result = executor.submit(method, *args, **kwargs) + return result def mock_invalid_lfid(): @@ -43,20 +43,6 @@ def mock_valid_lfid(): return _mock_valid_lfid -def upload(excepted_status, excepted_response): - def _upload(create_request): - @functools.wraps(create_request) - def wrap(self): - request = create_request(self) - status, body = self.upload(request) - if excepted_status == httplib.OK: - getattr(self, excepted_response)(body) - else: - self.assertIn(excepted_response, body) - return wrap - return _upload - - def create(excepted_status, excepted_response): def _create(create_request): @functools.wraps(create_request) @@ -105,7 +91,7 @@ def delete(excepted_status, excepted_response): def wrap(self): request = delete_request(self) if isinstance(request, tuple): - status, body = self.delete(request[0], *(request[1])) + status, body = self.delete(*request) else: status, body = self.delete(request) if excepted_status == httplib.OK: diff --git a/testapi/opnfv_testapi/tests/unit/fake_pymongo.py b/testapi/opnfv_testapi/tests/unit/fake_pymongo.py index 041e6e8..631e9ac 100644 --- a/testapi/opnfv_testapi/tests/unit/fake_pymongo.py +++ b/testapi/opnfv_testapi/tests/unit/fake_pymongo.py @@ -15,9 +15,9 @@ from concurrent.futures import ThreadPoolExecutor def thread_execute(method, *args, **kwargs): - with ThreadPoolExecutor(max_workers=2) as executor: - result = executor.submit(method, *args, **kwargs) - return result + with ThreadPoolExecutor(max_workers=2) as executor: + result = executor.submit(method, *args, **kwargs) + return result class MemCursor(object): diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_base.py b/testapi/opnfv_testapi/tests/unit/handlers/test_base.py index 6436b8b..1fd3324 100644 --- a/testapi/opnfv_testapi/tests/unit/handlers/test_base.py +++ b/testapi/opnfv_testapi/tests/unit/handlers/test_base.py @@ -35,20 +35,21 @@ class TestBase(testing.AsyncHTTPTestCase): details='zte pod 1', role='community-ci', _id=str(ObjectId()), - owner='ValidUser', + creator='ValidUser', creation_date=str(datetime.now())) self.pod_e = pod_models.Pod(name='zte-pod2', mode='metal', details='zte pod 2', role='production-ci', _id=str(ObjectId()), - owner='ValidUser', + creator='ValidUser', creation_date=str(datetime.now())) self.project_e = project_models.Project( name='functest', description='functest test', + creator='ValidUser', _id=str(ObjectId()), - create_date=str(datetime.now())) + creation_date=str(datetime.now())) self.req_d = None self.req_e = None @@ -62,7 +63,8 @@ class TestBase(testing.AsyncHTTPTestCase): 'opnfv-gerrit-functest-submitters', 'opnfv-gerrit-qtip-submitters', 'opnfv-gerrit-qtip-contributors', - 'opnfv-gerrit-apex-submitters'] + 'opnfv-gerrit-apex-submitters', + 'opnfv-gerrit-noProject-submitters'] }) def tearDown(self): @@ -157,7 +159,6 @@ class TestBase(testing.AsyncHTTPTestCase): res = self.fetch(url, method='DELETE', headers=self.headers) - return res.code, res.body def delete(self, *args): diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_deploy_result.py b/testapi/opnfv_testapi/tests/unit/handlers/test_deploy_result.py index 65e765e..8f2ca76 100644 --- a/testapi/opnfv_testapi/tests/unit/handlers/test_deploy_result.py +++ b/testapi/opnfv_testapi/tests/unit/handlers/test_deploy_result.py @@ -92,6 +92,10 @@ class DeployResultGet(DeployResultBase): self.req_d_id = self._create_d() self.req_10d_later = self._create_changed_date(days=10) + @executor.get(httplib.OK, 'assert_res') + def test_getOne(self): + return self.req_d_id + @executor.query(httplib.OK, '_query_success', 3) def test_queryInstaller(self): return self._set_query('installer') @@ -165,6 +169,19 @@ class DeployResultGet(DeployResultBase): self._create_error_start_date('') return self._set_query(period=5) + @executor.query(httplib.OK, '_query_success', 0) + def test_notFound(self): + return self._set_query('installer', + 'version', + 'job_name', + 'build_id', + 'scenario', + 'upstream_job_name', + 'upstream_build_id', + 'criteria', + pod='notExistPod', + period=1) + def _query_success(self, body, number): self.assertEqual(number, len(body.deployresults)) diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_pod.py b/testapi/opnfv_testapi/tests/unit/handlers/test_pod.py index 2818513..3a16799 100644 --- a/testapi/opnfv_testapi/tests/unit/handlers/test_pod.py +++ b/testapi/opnfv_testapi/tests/unit/handlers/test_pod.py @@ -10,6 +10,7 @@ import httplib from opnfv_testapi.common import message from opnfv_testapi.models import pod_models as pm +from opnfv_testapi.models import result_models as rm from opnfv_testapi.tests.unit import executor from opnfv_testapi.tests.unit import fake_pymongo from opnfv_testapi.tests.unit.handlers import test_base as base @@ -23,11 +24,13 @@ class TestPodBase(base.TestBase): self.basePath = '/api/v1/pods' self.req_d = pm.PodCreateRequest.from_dict(self.pod_d.format()) self.req_e = pm.PodCreateRequest.from_dict(self.pod_e.format()) + self.results_d = rm.ResultCreateRequest.from_dict( + self.load_json('test_result')) def assert_get_body(self, pod, req=None): if not req: req = self.req_d - self.assertEqual(pod, pm.Pod(owner='ValidUser', **req.format())) + self.assertEqual(pod, pm.Pod(creator='ValidUser', **req.format())) self.assertIsNotNone(pod.creation_date) self.assertIsNotNone(pod._id) @@ -101,3 +104,38 @@ class TestPodGet(TestPodBase): self.assert_get_body(pod) else: self.assert_get_body(pod, self.req_e) + + +class TestPodDelete(TestPodBase): + @executor.mock_valid_lfid() + def setUp(self): + super(TestPodDelete, self).setUp() + fake_pymongo.pods.insert(self.pod_d.format()) + fake_pymongo.projects.insert({'name': self.results_d.project_name}) + fake_pymongo.testcases.insert({ + 'name': self.results_d.case_name, + 'project_name': self.results_d.project_name}) + + @executor.delete(httplib.BAD_REQUEST, message.not_login()) + def test_notlogin(self): + return self.pod_d.name + + @executor.delete(httplib.NOT_FOUND, message.not_found_base) + def test_notFound(self): + return 'notFound' + + @executor.mock_valid_lfid() + @executor.delete(httplib.UNAUTHORIZED, message.tied_with_resource()) + def test_deleteNotAllowed(self): + self.create_help('/api/v1/results', self.results_d) + return self.pod_d.name + + @executor.mock_valid_lfid() + @executor.delete(httplib.OK, '_assert_delete') + def test_success(self): + return self.pod_d.name + + def _assert_delete(self, body): + self.assertEqual(body, '') + code, body = self.get(self.pod_d.name) + self.assertEqual(code, httplib.NOT_FOUND) diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_project.py b/testapi/opnfv_testapi/tests/unit/handlers/test_project.py index cbd1a4e..5903507 100644 --- a/testapi/opnfv_testapi/tests/unit/handlers/test_project.py +++ b/testapi/opnfv_testapi/tests/unit/handlers/test_project.py @@ -12,6 +12,7 @@ import urllib from opnfv_testapi.common import message from opnfv_testapi.models import project_models +from opnfv_testapi.models import testcase_models as tcm from opnfv_testapi.tests.unit import executor from opnfv_testapi.tests.unit.handlers import test_base as base @@ -23,6 +24,9 @@ class TestProjectBase(base.TestBase): 'qtip-ssh test') self.req_e = project_models.ProjectCreateRequest('functest', 'functest test') + self.testcase_d = tcm.TestcaseCreateRequest.from_dict( + self.load_json('testcase_d')) + self.project = 'qtip' self.get_res = project_models.Project self.list_res = project_models.Projects self.update_res = project_models.Project @@ -150,6 +154,15 @@ class TestProjectUpdate(TestProjectBase): return self.req_d, self.req_d.name @executor.mock_valid_lfid() + @executor.update(httplib.UNAUTHORIZED, message.tied_with_resource()) + def test_updateNotAllowed(self): + self.create_help('/api/v1/projects/%s/cases', + self.testcase_d, + self.req_d.name) + req = project_models.ProjectUpdateRequest('apex', 'apex test') + return req, self.req_d.name + + @executor.mock_valid_lfid() @executor.update(httplib.OK, '_assert_update') def test_success(self): req = project_models.ProjectUpdateRequest('apex', 'apex test') @@ -178,6 +191,14 @@ class TestProjectDelete(TestProjectBase): return 'notFound' @executor.mock_valid_lfid() + @executor.delete(httplib.UNAUTHORIZED, message.tied_with_resource()) + def test_deleteNotAllowed(self): + self.create_help('/api/v1/projects/%s/cases', + self.testcase_d, + self.req_d.name) + return self.req_d.name + + @executor.mock_valid_lfid() @executor.delete(httplib.OK, '_assert_delete') def test_success(self): return self.req_d.name diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_result.py b/testapi/opnfv_testapi/tests/unit/handlers/test_result.py index f1f055e..6435367 100644 --- a/testapi/opnfv_testapi/tests/unit/handlers/test_result.py +++ b/testapi/opnfv_testapi/tests/unit/handlers/test_result.py @@ -10,7 +10,6 @@ import copy from datetime import datetime from datetime import timedelta import httplib -import json import urllib from opnfv_testapi.common import message @@ -34,8 +33,9 @@ class TestResultBase(base.TestBase): self.basePath = '/api/v1/results' fake_pymongo.pods.insert({'name': self.req_d.pod_name}) fake_pymongo.projects.insert({'name': self.req_d.project_name}) - fake_pymongo.testcases.insert({'name': self.req_d.case_name, - 'project_name': self.req_d.project_name}) + fake_pymongo.testcases.insert({ + 'name': self.req_d.case_name, + 'project_name': self.req_d.project_name}) def assert_res(self, result, req=None): if req is None: @@ -46,22 +46,6 @@ class TestResultBase(base.TestBase): _, res = self.create_d() return res.href.split('/')[-1] - def upload(self, req): - if req and not isinstance(req, str) and hasattr(req, 'format'): - req = req.format() - res = self.fetch(self.basePath + '/upload', - method='POST', - body=json.dumps(req), - headers=self.headers) - - return self._get_return(res, self.create_res) - - -class TestResultUpload(TestResultBase): - @executor.upload(httplib.BAD_REQUEST, message.key_error('file')) - def test_filenotfind(self): - return None - class TestResultCreate(TestResultBase): @executor.create(httplib.BAD_REQUEST, message.no_body()) @@ -121,18 +105,6 @@ class TestResultCreate(TestResultBase): req.details = {'1.name': 'dot_name'} return req - @executor.create(httplib.OK, '_assert_no_ti') - def test_no_ti(self): - req = copy.deepcopy(self.req_d) - req.trust_indicator = rm.TI(0) - self.actual_req = req - return req - - def _assert_no_ti(self, body): - _id = body.href.split('/')[-1] - code, body = self.get(_id) - self.assert_res(body, self.actual_req) - class TestResultGet(TestResultBase): def setUp(self): @@ -174,10 +146,6 @@ class TestResultGet(TestResultBase): return self._set_query('scenario') @executor.query(httplib.OK, '_query_success', 3) - def test_queryTrustIndicator(self): - return self._set_query('trust_indicator') - - @executor.query(httplib.OK, '_query_success', 3) def test_queryCriteria(self): return self._set_query('criteria') @@ -197,16 +165,6 @@ class TestResultGet(TestResultBase): def test_queryLast(self): return self._set_query(last=1) - @executor.query(httplib.OK, '_query_success', 4) - def test_queryPublic(self): - self._create_public_data() - return self._set_query() - - @executor.query(httplib.OK, '_query_success', 1) - def test_queryPrivate(self): - self._create_private_data() - return self._set_query(public='false') - @executor.query(httplib.OK, '_query_period_one', 1) def test_combination(self): return self._set_query('pod', @@ -216,7 +174,6 @@ class TestResultGet(TestResultBase): 'installer', 'build_tag', 'scenario', - 'trust_indicator', 'criteria', period=5) @@ -228,7 +185,6 @@ class TestResultGet(TestResultBase): 'installer', 'build_tag', 'scenario', - 'trust_indicator', 'criteria', pod='notExistPod', period=1) @@ -266,24 +222,10 @@ class TestResultGet(TestResultBase): self.create(req) return req - def _create_public_data(self, **kwargs): - req = copy.deepcopy(self.req_d) - req.public = 'true' - self.create(req) - return req - - def _create_private_data(self, **kwargs): - req = copy.deepcopy(self.req_d) - req.public = 'false' - self.create(req) - return req - def _set_query(self, *args, **kwargs): def get_value(arg): if arg in ['pod', 'project', 'case']: return getattr(self.req_d, arg + '_name') - elif arg == 'trust_indicator': - return self.req_d.trust_indicator.current else: return getattr(self.req_d, arg) @@ -293,24 +235,3 @@ class TestResultGet(TestResultBase): for k, v in kwargs.iteritems(): query.append((k, v)) return urllib.urlencode(query) - - -class TestResultUpdate(TestResultBase): - def setUp(self): - super(TestResultUpdate, self).setUp() - self.req_d_id = self._create_d() - - @executor.update(httplib.OK, '_assert_update_ti') - def test_success(self): - update_date = str(datetime.now() + timedelta(days=1)) - update_step = -0.05 - self.after_update = copy.deepcopy(self.req_d) - self.after_update.trust_indicator.current += update_step - self.after_update.trust_indicator.histories.append( - rm.TIHistory(update_date, update_step)) - update = rm.ResultUpdateRequest( - trust_indicator=self.after_update.trust_indicator) - return update, self.req_d_id - - def _assert_update_ti(self, request, body): - self.assert_res(body, self.after_update) diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py b/testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py index 5d1b738..481078d 100644 --- a/testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py +++ b/testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py @@ -4,6 +4,7 @@ import httplib from opnfv_testapi.common import message import opnfv_testapi.models.scenario_models as sm +from opnfv_testapi.tests.unit import executor from opnfv_testapi.tests.unit.handlers import test_base as base @@ -20,6 +21,7 @@ class TestScenarioBase(base.TestBase): self.req_d = self.load_json('scenario-c1') self.req_2 = self.load_json('scenario-c2') + @executor.mock_valid_lfid() def create_return_name(self, req): _, res = self.create(req) return res.href.split('/')[-1] @@ -45,27 +47,32 @@ class TestScenarioBase(base.TestBase): class TestScenarioCreate(TestScenarioBase): + @executor.mock_valid_lfid() def test_withoutBody(self): (code, body) = self.create() self.assertEqual(code, httplib.BAD_REQUEST) + @executor.mock_valid_lfid() def test_emptyName(self): req_empty = sm.ScenarioCreateRequest('') (code, body) = self.create(req_empty) self.assertEqual(code, httplib.BAD_REQUEST) self.assertIn(message.missing('name'), body) + @executor.mock_valid_lfid() def test_noneName(self): req_none = sm.ScenarioCreateRequest(None) (code, body) = self.create(req_none) self.assertEqual(code, httplib.BAD_REQUEST) self.assertIn(message.missing('name'), body) + @executor.mock_valid_lfid() def test_success(self): (code, body) = self.create_d() self.assertEqual(code, httplib.OK) self.assert_create_body(body) + @executor.mock_valid_lfid() def test_alreadyExist(self): self.create_d() (code, body) = self.create_d() @@ -128,6 +135,7 @@ class TestScenarioDelete(TestScenarioBase): code, body = self.delete('notFound') self.assertEqual(code, httplib.NOT_FOUND) + @executor.mock_valid_lfid() def test_success(self): scenario = self.create_return_name(self.req_d) code, _ = self.delete(scenario) @@ -182,6 +190,7 @@ class TestScenarioUpdate(TestScenarioBase): return wrapper return _update_partial + @executor.mock_valid_lfid() @update_partial('_add', '_success') def test_addScore(self): add = sm.ScenarioScore(date=str(datetime.now()), score='11/12') @@ -193,6 +202,7 @@ class TestScenarioUpdate(TestScenarioBase): return add + @executor.mock_valid_lfid() @update_partial('_add', '_success') def test_addTrustIndicator(self): add = sm.ScenarioTI(date=str(datetime.now()), status='gold') @@ -204,6 +214,7 @@ class TestScenarioUpdate(TestScenarioBase): return add + @executor.mock_valid_lfid() @update_partial('_add', '_success') def test_addCustoms(self): adds = ['odl', 'parser', 'vping_ssh'] @@ -214,6 +225,7 @@ class TestScenarioUpdate(TestScenarioBase): self.locate_project) return adds + @executor.mock_valid_lfid() @update_partial('_update', '_success') def test_updateCustoms(self): updates = ['odl', 'parser', 'vping_ssh'] @@ -225,6 +237,7 @@ class TestScenarioUpdate(TestScenarioBase): return updates + @executor.mock_valid_lfid() @update_partial('_delete', '_success') def test_deleteCustoms(self): deletes = ['vping_ssh'] @@ -236,6 +249,7 @@ class TestScenarioUpdate(TestScenarioBase): return deletes + @executor.mock_valid_lfid() @update_url_fixture('projects') @update_partial('_add', '_success') def test_addProjects_succ(self): @@ -243,12 +257,14 @@ class TestScenarioUpdate(TestScenarioBase): self.req_d['installers'][0]['versions'][0]['projects'].append(add) return [add] + @executor.mock_valid_lfid() @update_url_fixture('projects') @update_partial('_add', '_conflict') def test_addProjects_already_exist(self): add = sm.ScenarioProject(project='functest').format() return [add] + @executor.mock_valid_lfid() @update_url_fixture('projects') @update_partial('_add', '_bad_request') def test_addProjects_bad_schema(self): @@ -256,6 +272,7 @@ class TestScenarioUpdate(TestScenarioBase): add['score'] = None return [add] + @executor.mock_valid_lfid() @update_url_fixture('projects') @update_partial('_update', '_success') def test_updateProjects_succ(self): @@ -263,12 +280,14 @@ class TestScenarioUpdate(TestScenarioBase): self.req_d['installers'][0]['versions'][0]['projects'] = [update] return [update] + @executor.mock_valid_lfid() @update_url_fixture('projects') @update_partial('_update', '_conflict') def test_updateProjects_duplicated(self): update = sm.ScenarioProject(project='qtip').format() return [update, update] + @executor.mock_valid_lfid() @update_url_fixture('projects') @update_partial('_update', '_bad_request') def test_updateProjects_bad_schema(self): @@ -276,6 +295,7 @@ class TestScenarioUpdate(TestScenarioBase): update['score'] = None return [update] + @executor.mock_valid_lfid() @update_url_fixture('projects') @update_partial('_delete', '_success') def test_deleteProjects(self): @@ -286,6 +306,7 @@ class TestScenarioUpdate(TestScenarioBase): projects) return deletes + @executor.mock_valid_lfid() @update_url_fixture('owner') @update_partial('_update', '_success') def test_changeOwner(self): @@ -294,6 +315,7 @@ class TestScenarioUpdate(TestScenarioBase): self.req_d['installers'][0]['versions'][0]['owner'] = new_owner return update + @executor.mock_valid_lfid() @update_url_fixture('versions') @update_partial('_add', '_success') def test_addVersions_succ(self): @@ -301,12 +323,14 @@ class TestScenarioUpdate(TestScenarioBase): self.req_d['installers'][0]['versions'].append(add) return [add] + @executor.mock_valid_lfid() @update_url_fixture('versions') @update_partial('_add', '_conflict') def test_addVersions_already_exist(self): add = sm.ScenarioVersion(version='master').format() return [add] + @executor.mock_valid_lfid() @update_url_fixture('versions') @update_partial('_add', '_bad_request') def test_addVersions_bad_schema(self): @@ -314,6 +338,7 @@ class TestScenarioUpdate(TestScenarioBase): add['notexist'] = None return [add] + @executor.mock_valid_lfid() @update_url_fixture('versions') @update_partial('_update', '_success') def test_updateVersions_succ(self): @@ -321,12 +346,14 @@ class TestScenarioUpdate(TestScenarioBase): self.req_d['installers'][0]['versions'] = [update] return [update] + @executor.mock_valid_lfid() @update_url_fixture('versions') @update_partial('_update', '_conflict') def test_updateVersions_duplicated(self): update = sm.ScenarioVersion(version='euphrates').format() return [update, update] + @executor.mock_valid_lfid() @update_url_fixture('versions') @update_partial('_update', '_bad_request') def test_updateVersions_bad_schema(self): @@ -334,6 +361,7 @@ class TestScenarioUpdate(TestScenarioBase): update['not_owner'] = 'Iam' return [update] + @executor.mock_valid_lfid() @update_url_fixture('versions') @update_partial('_delete', '_success') def test_deleteVersions(self): @@ -344,6 +372,7 @@ class TestScenarioUpdate(TestScenarioBase): versions) return deletes + @executor.mock_valid_lfid() @update_url_fixture('installers') @update_partial('_add', '_success') def test_addInstallers_succ(self): @@ -351,12 +380,14 @@ class TestScenarioUpdate(TestScenarioBase): self.req_d['installers'].append(add) return [add] + @executor.mock_valid_lfid() @update_url_fixture('installers') @update_partial('_add', '_conflict') def test_addInstallers_already_exist(self): add = sm.ScenarioInstaller(installer='apex').format() return [add] + @executor.mock_valid_lfid() @update_url_fixture('installers') @update_partial('_add', '_bad_request') def test_addInstallers_bad_schema(self): @@ -364,6 +395,7 @@ class TestScenarioUpdate(TestScenarioBase): add['not_exist'] = 'not_exist' return [add] + @executor.mock_valid_lfid() @update_url_fixture('installers') @update_partial('_update', '_success') def test_updateInstallers_succ(self): @@ -371,12 +403,14 @@ class TestScenarioUpdate(TestScenarioBase): self.req_d['installers'] = [update] return [update] + @executor.mock_valid_lfid() @update_url_fixture('installers') @update_partial('_update', '_conflict') def test_updateInstallers_duplicated(self): update = sm.ScenarioInstaller(installer='daisy').format() return [update, update] + @executor.mock_valid_lfid() @update_url_fixture('installers') @update_partial('_update', '_bad_request') def test_updateInstallers_bad_schema(self): @@ -384,6 +418,7 @@ class TestScenarioUpdate(TestScenarioBase): update['not_exist'] = 'not_exist' return [update] + @executor.mock_valid_lfid() @update_url_fixture('installers') @update_partial('_delete', '_success') def test_deleteInstallers(self): @@ -394,6 +429,7 @@ class TestScenarioUpdate(TestScenarioBase): installers) return deletes + @executor.mock_valid_lfid() @update_url_fixture('rename') @update_partial('_update', '_success') def test_renameScenario(self): @@ -402,6 +438,7 @@ class TestScenarioUpdate(TestScenarioBase): self.req_d['name'] = new_name return update + @executor.mock_valid_lfid() @update_url_fixture('rename') @update_partial('_update', '_forbidden') def test_renameScenario_exist(self): diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py b/testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py index 9a2bf58..e0ce381 100644 --- a/testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py +++ b/testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py @@ -10,6 +10,7 @@ import httplib from opnfv_testapi.common import message from opnfv_testapi.models import testcase_models as tcm +from opnfv_testapi.models import result_models as rm from opnfv_testapi.tests.unit import executor from opnfv_testapi.tests.unit import fake_pymongo from opnfv_testapi.tests.unit.handlers import test_base as base @@ -31,7 +32,8 @@ class TestCaseBase(base.TestBase): self.update_res = tcm.Testcase self.basePath = '/api/v1/projects/%s/cases' fake_pymongo.projects.insert(self.project_e.format()) - print self.req_d.format() + self.results_d = rm.ResultCreateRequest.from_dict( + self.load_json('test_result')) def assert_body(self, case, req=None): if not req: @@ -69,8 +71,8 @@ class TestCaseBase(base.TestBase): return super(TestCaseBase, self).update(new, self.project, case) @executor.mock_valid_lfid() - def delete(self, case): - return super(TestCaseBase, self).delete(self.project, case) + def delete(self, case=None, project=None): + return super(TestCaseBase, self).delete(project, case) class TestCaseCreate(TestCaseBase): @@ -78,6 +80,11 @@ class TestCaseCreate(TestCaseBase): def test_noBody(self): return None + @executor.create(httplib.FORBIDDEN, message.no_permission()) + def test_unauthorized(self): + self.project = 'newProject' + return self.req_d + @executor.create(httplib.FORBIDDEN, message.not_found_base) def test_noProject(self): self.project = 'noProject' @@ -151,6 +158,12 @@ class TestCaseUpdate(TestCaseBase): self.create_e() return self.update_req, self.req_d.name + @executor.update(httplib.FORBIDDEN, message.no_permission()) + def test_unauthorized(self): + update_req_e = tcm.TestcaseUpdateRequest(project_name="newProject", + **self.req_e.format()) + return update_req_e, self.req_d.name + @executor.update(httplib.FORBIDDEN, message.no_update()) def test_noUpdate(self): update = tcm.TestcaseUpdateRequest(project_name=self.project, @@ -176,14 +189,31 @@ class TestCaseDelete(TestCaseBase): def setUp(self): super(TestCaseDelete, self).setUp() self.create_d() + fake_pymongo.pods.insert(self.pod_d.format()) + fake_pymongo.projects.insert({'name': self.results_d.project_name}) + fake_pymongo.testcases.insert({ + 'name': self.results_d.case_name, + 'project_name': self.results_d.project_name}) + fake_pymongo.testcases.insert({ + 'name': 'newCase', + 'project_name': 'newProject'}) @executor.delete(httplib.NOT_FOUND, message.not_found_base) def test_notFound(self): - return 'notFound' + return 'notFound', self.project + + @executor.delete(httplib.FORBIDDEN, message.no_permission()) + def test_unauthorized(self): + return 'newCase', 'newProject' + + @executor.delete(httplib.UNAUTHORIZED, message.tied_with_resource()) + def test_deleteNotAllowed(self): + self.create_help('/api/v1/results', self.results_d) + return self.results_d.case_name, self.project @executor.delete(httplib.OK, '_delete_success') def test_success(self): - return self.req_d.name + return self.req_d.name, self.project def _delete_success(self, body): self.assertEqual(body, '') diff --git a/testapi/opnfv_testapi/tests/unit/templates/test_result.json b/testapi/opnfv_testapi/tests/unit/templates/test_result.json index b7cb910..8f1d5fa 100644 --- a/testapi/opnfv_testapi/tests/unit/templates/test_result.json +++ b/testapi/opnfv_testapi/tests/unit/templates/test_result.json @@ -1,10 +1,6 @@ { "project_name": "functest", "scenario": "odl-l2", - "trust_indicator": { - "current": 0.7, - "histories": [] - }, "case_name": "vPing", "build_tag": "v3.0", "public": "true", diff --git a/testapi/opnfv_testapi/ui/Gruntfile.js b/testapi/opnfv_testapi/ui/Gruntfile.js index 72a47e1..d6a2f47 100644 --- a/testapi/opnfv_testapi/ui/Gruntfile.js +++ b/testapi/opnfv_testapi/ui/Gruntfile.js @@ -6,7 +6,22 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-wait'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-connect'); + grunt.loadNpmTasks('grunt-convert'); grunt.initConfig({ + convert: { + options: { + explicitArray: false, + }, + json2xml: { + options: { + xml: { + header: true + } + }, + src: ['../tests/UI/coverage/coverage.json'], + dest: '../tests/UI/coverage/coverage.xml' + } + }, connect: { server: { options: { @@ -115,19 +130,29 @@ module.exports = function (grunt) { noColor: false, coverageDir: '../tests/UI/coverage', args: { - specs: ['../tests/UI/e2e/testCasesControllerSpec.js', - '../tests/UI/e2e/resultsControllerSpec.js'] + specs: [ + '../tests/UI/e2e/homeControllerSpec.js', + '../tests/UI/e2e/podsControllerSpec.js', + '../tests/UI/e2e/projectsControllerSpec.js', + '../tests/UI/e2e/testCasesControllerSpec.js', + '../tests/UI/e2e/resultsControllerSpec.js', + '../tests/UI/e2e/scenariosControllerSpec.js', + '../tests/UI/e2e/scenarioControllerSpec.js', + '../tests/UI/e2e/deployResultsControllerSpec.js', + '../tests/UI/e2e/authenticateFalseSpec.js' + ] } }, local: { options: { - configFile: '../tests/UI/protractor-conf.js' + configFile: 'protractor-conf.js' } } }, makeReport: { src: '../tests/UI/coverage/*.json', options: { + type: 'cobertura', print: 'detail' } } @@ -150,6 +175,7 @@ module.exports = function (grunt) { 'wait:default', 'protractor_coverage', 'makeReport', + 'convert', 'shell:deleteFiles' ]); } diff --git a/testapi/opnfv_testapi/ui/app.js b/testapi/opnfv_testapi/ui/app.js index 3da12b1..3fb4bc7 100644 --- a/testapi/opnfv_testapi/ui/app.js +++ b/testapi/opnfv_testapi/ui/app.js @@ -19,7 +19,7 @@ angular .module('testapiApp', [ 'ui.router','ui.bootstrap', 'cgBusy', - 'ngResource', 'angular-confirm' + 'ngResource', 'angular-confirm', 'angular-json-tree' ]); angular @@ -28,6 +28,57 @@ angular .module('testapiApp') + .service("keepState", function(){ + this.filter = {}; + }); + + angular + .module('testapiApp') + .service('sortService', function(){ + + this.sortFunction = function(data, field, ascending){ + if(ascending){ + data.sort(function(a,b) { + if (a[field].toLowerCase() > b[field].toLowerCase()) { + return -1; + } + if (a[field].toLowerCase() < b[field].toLowerCase()) { + return 1; + } + return 0; + }); + }else{ + data.sort(function(a,b) { + if (a[field].toLowerCase() < b[field].toLowerCase()) { + return -1; + } + if (a[field].toLowerCase() > b[field].toLowerCase()) { + return 1; + } + return 0; + }); + } + return data + } + }); + + angular + .module('testapiApp') + .service('dataFieldService', function(){ + this.dataFunction = dataFunction + function dataFunction(data, data_field){ + Object.keys(data).forEach(function (key) { + if (typeof data[key] === 'object' && data[key] != null) { + return dataFunction(data[key], data_field); + } + data_field[key] = key.replace(/_/g, " ").trim(); + }); + return data_field; + } + }); + + angular + .module('testapiApp') .directive('dynamicModel', ['$compile', '$parse', function ($compile, $parse) { return { restrict: 'A', @@ -42,6 +93,21 @@ }; }]); + angular + .module('testapiApp') + .directive('ngEnter', function () { + return function (scope, element, attrs) { + element.bind("keydown keypress", function (event) { + if(event.which === 13) { + scope.$apply(function (){ + scope.$eval(attrs.ngEnter); + }); + event.preventDefault(); + } + }); + }; + }); + configureRoutes.$inject = ['$stateProvider', '$urlRouterProvider']; /** @@ -79,6 +145,16 @@ templateUrl: 'testapi-ui/components/projects/project/project.html', controller: 'ProjectController as ctrl' }). + state('scenarios', { + url: '/scenarios', + templateUrl: 'testapi-ui/components/scenarios/scenarios.html', + controller: 'ScenariosController as ctrl' + }). + state('scenario', { + url: '/scenarios/:name', + templateUrl: 'testapi-ui/components/scenarios/scenario/scenario.html', + controller: 'ScenarioController as ctrl' + }). state('testCase', { url: '/projects/:project_name/:name', templateUrl: 'testapi-ui/components/projects/project/testCases/testCase/testCase.html', @@ -94,6 +170,16 @@ templateUrl: 'testapi-ui/components/results/result/result.html', controller: 'ResultController as ctrl' }). + state('deployresults', { + url: '/deployresults', + templateUrl: 'testapi-ui/components/deploy-results/deployResults.html', + controller: 'DeployResultsController as ctrl' + }). + state('deployresult', { + url: '/deployresults/:_id', + templateUrl: 'testapi-ui/components/deploy-results/deploy-result/deployResult.html', + controller: 'DeployResultController as ctrl' + }). state('profile', { url: '/profile', templateUrl: 'testapi-ui/components/profile/profile.html', @@ -144,6 +230,7 @@ function setup($http, $rootScope, $window, $state, testapiApiUrl, authenticate) { $rootScope.auth = {}; + $rootScope.authenticate = authenticate $rootScope.auth.doSignIn = doSignIn; $rootScope.auth.doSignOut = doSignOut; $rootScope.auth.doSignCheck = doSignCheck; @@ -160,10 +247,14 @@ /** This function will initate a sign out. */ function doSignOut() { - $rootScope.auth.currentUser = null; - $rootScope.auth.isAuthenticated = false; - $rootScope.auth.projectNames = []; - $window.location.href = sign_out_url; + if(authenticate){ + $rootScope.auth.currentUser = null; + $rootScope.auth.isAuthenticated = false; + $rootScope.auth.projectNames = []; + $window.location.href = sign_out_url; + }else{ + $state.go("home", {reload: true}) + } } /** @@ -171,21 +262,23 @@ * authenticated. */ function doSignCheck() { - return $http.get(profile_url, {withCredentials: true}). - success(function (data) { - $rootScope.auth.currentUser = data; - $rootScope.auth.isAuthenticated = true; - if(authenticate){ + if(authenticate){ + return $http.get(profile_url, {withCredentials: true}). + success(function (data) { + $rootScope.auth.currentUser = data; + $rootScope.auth.isAuthenticated = true; $rootScope.auth.projectNames = $rootScope.auth.doSubmitterCheck(data.groups); - }else{ - $rootScope.auth.projectNames = ["anonymous"] - } - }). - error(function () { - $rootScope.auth.currentUser = null; - $rootScope.auth.isAuthenticated = false; - $rootScope.auth.projectNames = []; - }); + }). + error(function () { + $rootScope.auth.currentUser = null; + $rootScope.auth.isAuthenticated = false; + $rootScope.auth.projectNames = []; + }); + }else{ + $rootScope.auth.currentUser = null; + $rootScope.auth.isAuthenticated = true; + $rootScope.auth.projectNames = [] + } } function doSubmitterCheck(groups){ diff --git a/testapi/opnfv_testapi/ui/components/deploy-results/deploy-result/deployResult.html b/testapi/opnfv_testapi/ui/components/deploy-results/deploy-result/deployResult.html new file mode 100644 index 0000000..c0803ff --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/deploy-results/deploy-result/deployResult.html @@ -0,0 +1,31 @@ +<legend>Result</legend> +<div style="padding-right:0px"> + <div class="table-responsive"> + <table class="table" ng-data="ctrl.data.pods"> + <tbody> + <tr ng-repeat-start="(index, detail) in ctrl.data_field" style="padding:9px"> + <td class="podsTableTd">{{detail | capitalize}} :</td> + <td width="86%" class="podsTableLeftTd">{{ctrl.data[index]}}</td> + </tr> + <tr ng-repeat-end=> + </tr> + <tr style="padding:9px"> + <td class="podsTableTd">Details :</td> + <td width="86%" class="podsTableLeftTd"> + <json-tree object="ctrl.json.object" root-name="object" start-expanded="true"></json-tree> + </td> + </tr> + </tbody> + </table> + </div> +</div> +<div class="col-md-12"> + <div ng-show="ctrl.showError" class="col-md-12 alert alert-danger" role="alert"> + <span class="pull-right"> {{ctrl.error}}</span> + <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span> + </div> + <div ng-show="ctrl.showSuccess" class="col-md-12 alert alert-success" role="alert"> + <span class="pull-right"> {{ctrl.success}}</span> + <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span> + </div> + </div>
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/deploy-results/deploy-result/deployResultController.js b/testapi/opnfv_testapi/ui/components/deploy-results/deploy-result/deployResultController.js new file mode 100644 index 0000000..6f9b84c --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/deploy-results/deploy-result/deployResultController.js @@ -0,0 +1,66 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file 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. + */ + +(function () { + 'use strict'; + + angular + .module('testapiApp') + .controller('DeployResultController', DeployResultController); + + DeployResultController.$inject = [ + '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert', + 'confirmModal', 'dataFieldService' + ]; + + /** + * TestAPI DeployResultController + * This controller is for the '/result/:_id' page where a user can browse + * through result declared in TestAPI. + */ + function DeployResultController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl, + raiseAlert, confirmModal, dataFieldService) { + var ctrl = this; + ctrl.url = testapiApiUrl + '/deployresults'; + ctrl._id = $state.params['_id']; + ctrl.loadDetails = loadDetails + ctrl.data_field = {} + + ctrl.json = {}; + ctrl.json.string = '{"id": ""}'; + ctrl.json.object = JSON.parse(ctrl.json.string); + + /** + *Contact the testapi and retrevie the result details + */ + function loadDetails(){ + var resultUrl = ctrl.url + '/' + ctrl._id; + ctrl.showError = false; + ctrl.podsRequest = + $http.get(resultUrl).success(function (data) { + ctrl.data = data; + ctrl.object=JSON.stringify(ctrl.data.details) + ctrl.json.object = JSON.parse(ctrl.object) + delete ctrl.data.details; + ctrl.data_field = dataFieldService.dataFunction(ctrl.data, ctrl.data_field) + }).catch(function (error) { + ctrl.data = null; + ctrl.showError = true; + ctrl.error = error.statusText; + }); + } + + ctrl.loadDetails(); + } +})();
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/deploy-results/deployResults.html b/testapi/opnfv_testapi/ui/components/deploy-results/deployResults.html new file mode 100644 index 0000000..7998f3c --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/deploy-results/deployResults.html @@ -0,0 +1,130 @@ +<h3>{{ctrl.pageHeader}}</h3> +<p>{{ctrl.pageParagraph}}</p> +<div class="row" style="margin-bottom:24px;"></div> +<div class="result-filters" style="border-top: none;"> + <div class="row podTable" style="vertical-align:middle"> + <div class="col-sm-1 pull-right"> + <button type="button" class="btn btn-danger" ng-click="ctrl.clearFilters()"> + <i class="fa fa-search"></i> Clear + </button> + </div> + <div class="col-sm-1 pull-right"> + <button type="button" class="btn btn-success" ng-click="ctrl.filterList()"> + <i class="fa fa-search"></i> Filter</button> + </div> + <div class="col-sm-2 pull-right" ng-class="{'hidden': ctrl.filter=='start_date' || ctrl.filter=='end_date'}"> + <span style="margin-top:6px">Search: </span> + <input list="filter" name="filter" class="form-control search" style="display:inline;width:105px;padding-left:6px;" + ng-enter="ctrl.filterList()" ng-Model="ctrl.filterText" placeholder="Search String"> + <datalist id="filter" ng-class="{ 'hidden' : ctrl.filterOption.length<0}"> + <option ng-repeat="(index, filterValue) in ctrl.filterOption " value="{{filterValue}}">{{filterValue}}</option> + </datalist> + </div> + <div class="col-sm-3 pull-right" style="width:20%" ng-class="{'hidden': ctrl.filter!='start_date'}"> + <span style="margin-top:6px">Start Date: </span> + <p class="input-group" style="width:48%;display:inline-flex;"> + <input type="text" class="form-control" + ng-enter="ctrl.filterList()" + uib-datepicker-popup="{{ctrl.format}}" + ng-model="ctrl.filterText" is-open="ctrl.startOpen" + close-text="Close" /> + <span class="input-group-btn"> + <button type="button" class="btn btn-default" ng-click="ctrl.open($event, 'startOpen')"> + <i class="glyphicon glyphicon-calendar"></i> + </button> + </span> + </p> + </div> + <div class="col-sm-3 pull-right" style="width:20%" ng-class="{'hidden': ctrl.filter!='end_date'}"> + <span style="margin-top:6px">End Date: </span> + <p class="input-group" style="width:48%;display:inline-flex;"> + <input type="text" class="form-control" + ng-enter="ctrl.filterList()" + uib-datepicker-popup="{{ctrl.format}}" + ng-model="ctrl.filterText" is-open="ctrl.endOpen" + close-text="Close" /> + <span class="input-group-btn"> + <button type="button" class="btn btn-default" ng-click="ctrl.open($event, 'endOpen')"> + <i class="glyphicon glyphicon-calendar"></i> + </button> + </span> + </p> + </div> + <div class="col-md-2 row pull-right" style="width: 20%;"> + <span style="margin-top:6px">Filter: </span> + <select ng-model="ctrl.filter" ng-change="ctrl.encodeFilter()" class="form-control" style="display:inline; width:150px;"> + <option value="pod" ng-disabled="ctrl.testFilter('pod')" >Pod Name</option> + <option value="job_name" ng-disabled="ctrl.testFilter('job_name')" >Job Name</option> + <option value="installer" ng-disabled="ctrl.testFilter('installer')">Installer</option> + <option value="version" ng-disabled="ctrl.testFilter('version')">Version</option> + <option value="scenario" ng-disabled="ctrl.testFilter('scenario')">Scenario</option> + <option value="build_id" ng-disabled="ctrl.testFilter('build_id')">Build ID</option> + <option value="criteria" ng-disabled="ctrl.testFilter('criteria')">Criteria</option> + <option value="start_date" ng-disabled="ctrl.testFilter('start_date')">Start Date</option> + <option value="end_date" ng-disabled="ctrl.testFilter('end_date')">End Date</option> + </select> + </div> + <div class='filter-box'> + <div class='filter-tag col-md-1' ng-repeat="(key, tag) in ctrl.tagArray" style="background-color: #f5f5f5;border: 1px solid #e3e3e3;/* border: 1px; */margin-top: 3px;padding: 4px;margin-left: 15px;width: 13%;"> + {{key}} : {{tag}} + <div class='delete-tag btn btn-danger btn-xs' ng-click='ctrl.deleteTag(key)'> + × + </div> + </div> + </div> + </div> +</div> + +<div cg-busy="{promise:ctrl.authRequest,message:'Loading'}"></div> +<div cg-busy="{promise:ctrl.resultsRequest,message:'Loading'}"></div> +<div ng-show="ctrl.data" class="results-table"> + <table ng-data="ctrl.data.deployresults" ng-show="ctrl.data" class="table table-striped table-hover"> + <thead> + <tr> + <th>ID</th> + <th>Installer</th> + <th>Version</th> + <th>Scenario</th> + <th>Pod</th> + <th>Criteria</th> + <th>Start Date</th> + <th>Stop Date</th> + </tr> + </thead> + + <tbody> + <tr ng-repeat-start="(index, result) in ctrl.data.deployresults"> + <td><a ng-click="ctrl.viewDeployResult(result._id)">{{ result._id.substr(-8) }}</a></td> + <td>{{ result.installer }}</td> + <td>{{ result.version }}</td> + <td>{{ result.scenario }}</td> + <td>{{ result.pod_name }}</td> + <td>{{ result.criteria }}</td> + <td>{{ result.start_date }}</td> + <td>{{ result.stop_date }}</td> + </tr> + <tr ng-repeat-end=> + </tr> + </tbody> + </table> + + <div class="pages"> + <uib-pagination + total-items="ctrl.totalItems" + ng-model="ctrl.currentPage" + items-per-page="ctrl.itemsPerPage" + max-size="ctrl.maxSize" + class="pagination-sm" + boundary-links="true" + rotate="false" + num-pages="ctrl.numPages" + ng-change="ctrl.filterList()"> + </uib-pagination> + </div> +</div> + +<div ng-show="ctrl.showError" class="alert alert-danger" role="alert"> + <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> + <span class="sr-only">Error:</span> + {{ctrl.error}} +</div> diff --git a/testapi/opnfv_testapi/ui/components/deploy-results/deployResultsController.js b/testapi/opnfv_testapi/ui/components/deploy-results/deployResultsController.js new file mode 100644 index 0000000..1128825 --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/deploy-results/deployResultsController.js @@ -0,0 +1,200 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file 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. + */ + +(function () { + 'use strict'; + + angular + .module('testapiApp') + .controller('DeployResultsController', DeployResultsController); + + DeployResultsController.$inject = [ + '$scope', '$http', '$filter', '$state', 'testapiApiUrl','raiseAlert', + 'keepState' + ]; + + /** + * TestAPI Deploy Results Controller + * This controller is for the '/deployresults' page where a user can browse + * a listing of community uploaded results. + */ + function DeployResultsController($scope, $http, $filter, $state, testapiApiUrl, + raiseAlert, keepState) { + var ctrl = this; + + ctrl.open = open; + ctrl.clearFilters = clearFilters; + ctrl.deleteTag = deleteTag; + ctrl.filterList= filterList; + ctrl.testFilter = testFilter + ctrl.filter = "pod" + ctrl.filterValue = "pod_name" + ctrl.encodeFilter = encodeFilter + ctrl.viewDeployResult = viewDeployResult + ctrl.tagArray = {} + ctrl.filterOption=[] + + /** Initial page to be on. */ + ctrl.currentPage = 1; + + /** + * How many results should display on each page. Since pagination + * is server-side implemented, this value should match the + * 'results_per_page' configuration of the TestAPI server which + * defaults to 20. + */ + ctrl.itemsPerPage = 20; + + /** + * How many page buttons should be displayed at max before adding + * the '...' button. + */ + ctrl.maxSize = 5; + + /** The upload date lower limit to be used in filtering results. */ + ctrl.startDate = ''; + + /** The upload date upper limit to be used in filtering results. */ + ctrl.endDate = ''; + + /** The date format for the date picker. */ + ctrl.format = 'yyyy-MM-dd'; + + ctrl.pageHeader = "Deploy Results" + + ctrl.pageParagraph = 'Your most recently uploaded deploy results are listed here.' + ctrl.isPublic = false; + + function encodeFilter(){ + ctrl.filterText = '' + ctrl.filterOption=[] + if(ctrl.filter=="pod" || ctrl.filter=="scenario"){ + var reqURL = testapiApiUrl +"/" + ctrl.filter + "s" + ctrl.datasRequest = + $http.get(reqURL).success(function (data) { + ctrl.filterData = data; + for(var index in ctrl.filterData[ctrl.filter + "s"]){ + if( ctrl.filterOption.indexOf(ctrl.filterData[ctrl.filter + "s"][index]["name"]) < 0){ + ctrl.filterOption.push(ctrl.filterData[ctrl.filter + "s"][index]["name"]) + } + } + }).catch(function (data) { + ctrl.data = null; + ctrl.showError = true; + ctrl.error = data.statusText; + }); + + } + } + + function deleteTag(index){ + delete ctrl.tagArray[index]; + ctrl.filterList(); + } + + function testFilter(text){ + for (var filter in ctrl.tagArray){ + if(text==filter){ + return true; + } + } + return false; + } + + function viewDeployResult(_id){ + $state.go('deployresult', {'_id':_id}, {reload: true}); + } + + /** + * This will contact the TestAPI API to get a listing of deploy + * results. + */ + function filterList(){ + if(ctrl.filter && ctrl.filterText!="" && ctrl.filterText!=undefined){ + ctrl.tagArray[ctrl.filter] = ctrl.filterText; + if(!keepState.filter.deployResultFilter){ + keepState.filter.deployResultFilter = {} + } + keepState.filter.deployResultFilter[ctrl.filter] = ctrl.filterText + } + else if(Object.keys(ctrl.tagArray).length==0){ + if(keepState.filter.deployResultFilter){ + ctrl.tagArray = keepState.filter.deployResultFilter + } + } + ctrl.showError = false; + var content_url = testapiApiUrl + '/deployresults' + + '?page=' + ctrl.currentPage; + for(var key in ctrl.tagArray){ + if(key=="start_date"){ + var start = $filter('date')(ctrl.tagArray[key], 'yyyy-MM-dd'); + if (start) { + content_url = + content_url + '&from=' + start + ' 00:00:00'; + } + } + else if(key=="end_date"){ + var end = $filter('date')(ctrl.tagArray[key], 'yyyy-MM-dd'); + if (end) { + content_url = content_url + '&to=' + end + ' 23:59:59'; + } + } + else{ + content_url = content_url + "&" + key + "=" + ctrl.tagArray[key] + } + if (ctrl.isUserResults) { + content_url = content_url + '&signed'; + } + } + ctrl.resultsRequest = + $http.get(content_url).success(function (data) { + ctrl.data = data; + ctrl.totalItems = ctrl.data.pagination.total_pages * ctrl.itemsPerPage; + ctrl.currentPage = ctrl.data.pagination.current_page; + ctrl.encodeFilter(); + }).catch(function (error) { + ctrl.data = null; + ctrl.totalItems = 0; + ctrl.showError = true; + ctrl.error = error.statusText + }); + ctrl.filterText = '' + } + ctrl.filterList(); + + + /** + * This is called when the date filter calendar is opened. It + * does some event handling, and sets a scope variable so the UI + * knows which calendar was opened. + * @param {Object} $event - The Event object + * @param {String} openVar - Tells which calendar was opened + */ + function open($event, openVar) { + $event.preventDefault(); + $event.stopPropagation(); + ctrl[openVar] = true; + } + + /** + * This function will clear all filters and update the results + * listing. + */ + function clearFilters() { + ctrl.tagArray = {} + ctrl.filter = undefined + ctrl.filterList(); + } + } +})(); diff --git a/testapi/opnfv_testapi/ui/components/pods/pod/pod.html b/testapi/opnfv_testapi/ui/components/pods/pod/pod.html index b78eb2d..f9ab7c1 100644 --- a/testapi/opnfv_testapi/ui/components/pods/pod/pod.html +++ b/testapi/opnfv_testapi/ui/components/pods/pod/pod.html @@ -3,33 +3,11 @@ <div class="table-responsive"> <table class="table" ng-data="ctrl.data.pods"> <tbody> - <tr style="padding:9px"> - <td class="podsTableTd">Id :</td> - <td class="podsTableLeftTd">{{ctrl.data._id}}</td> + <tr ng-repeat-start="(index, detail) in ctrl.data_field" style="padding:9px"> + <td class="podsTableTd">{{detail | capitalize}} :</td> + <td width="90%" class="podsTableLeftTd">{{ctrl.data[index]}}</td> </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Name :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.name}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Owner :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.owner}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Role :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.role}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Mode :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.mode}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Created at :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data['creation_date']}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Details :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.details}}</td> + <tr ng-repeat-end=> </tr> </tbody> </table> diff --git a/testapi/opnfv_testapi/ui/components/pods/pod/podController.js b/testapi/opnfv_testapi/ui/components/pods/pod/podController.js index a2e18e8..39ba599 100644 --- a/testapi/opnfv_testapi/ui/components/pods/pod/podController.js +++ b/testapi/opnfv_testapi/ui/components/pods/pod/podController.js @@ -21,7 +21,7 @@ PodController.$inject = [ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert', - 'confirmModal' + 'confirmModal', 'dataFieldService' ]; /** @@ -30,11 +30,12 @@ * through pod declared in TestAPI. */ function PodController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl, - raiseAlert, confirmModal) { + raiseAlert, confirmModal, dataFieldService) { var ctrl = this; ctrl.url = testapiApiUrl + '/pods'; ctrl.name = $state.params['name']; - ctrl.loadDetails = loadDetails + ctrl.loadDetails = loadDetails; + ctrl.data_field = {}; /** *Contact the testapi and retrevie the pod details @@ -45,6 +46,7 @@ ctrl.podsRequest = $http.get(podUrl).success(function (data) { ctrl.data = data; + ctrl.data_field = dataFieldService.dataFunction(ctrl.data, ctrl.data_field) }).catch(function (error) { ctrl.data = null; ctrl.showError = true; diff --git a/testapi/opnfv_testapi/ui/components/pods/pods.html b/testapi/opnfv_testapi/ui/components/pods/pods.html index e092699..b5dadf5 100644 --- a/testapi/opnfv_testapi/ui/components/pods/pods.html +++ b/testapi/opnfv_testapi/ui/components/pods/pods.html @@ -19,29 +19,18 @@ <div class="col-sm-1 pull-right"> <button type="button" class="btn btn-success" ng-click="ctrl.listPods()"> <i class="fa fa-search"></i> Filter</button> + <div ng-class="{'show': ctrl.showError}" id="toast" class="error"> + <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true" ></span> + {{ctrl.error}}</div> + <div ng-class="{'show': ctrl.showSuccess}" id="toast" class="success"> + <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> + {{ctrl.success}}</div> </div> <div class="col-sm-3 pull-right"> <span style="margin-top:6px">Search: </span> - <input type="text" class="form-control search" ngModel="filter" placeholder="Search String"> - </div> - <div class="col-md-3 row pull-right"> - <span style="margin-top:6px">Filter: </span> - <select ng-model="ctrl.filter" class="form-control"> - <option value="name">Name</option> - <option value="owner">Owner</option> - </select> + <input type="text" class="form-control search" ng-enter="ctrl.listPods()" ng-Model="ctrl.filterText" placeholder="Search String"> </div> </div> -<div class="col-md-12"> - <div ng-show="ctrl.showError" class="col-md-12 alert alert-danger" role="alert"> - <span class="pull-right"> {{ctrl.error}}</span> - <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span> - </div> - <div ng-show="ctrl.showSuccess" class="col-md-12 alert alert-success" role="alert"> - <span class="pull-right"> {{ctrl.success}}</span> - <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span> - </div> -</div> <div class="col-md-12" style="padding-right:0px"> <div class="table-responsive"> <table class="table table-bordered table-hover" ng-data="ctrl.data.pods"> @@ -49,9 +38,30 @@ <tr style=" text-align: center;"> <th style="width:1%">Bulk Select</th> - <th>Name</th> - <th>Role</th> - <th>Mode</th> + <th>Name + <a class="text-danger" ng-click="ctrl.sortBy('name')" ng-class="{ 'hidden': !ctrl.sorting['name'] }" > + <span class="glyphicon glyphicon-sort-by-alphabet pull-right" aria-hidden="true"></span> + </a> + <a class="text-danger" ng-click="ctrl.sortBy('name')" ng-class="{ 'hidden': ctrl.sorting['name'] }" > + <span class="glyphicon glyphicon-sort-by-alphabet-alt pull-right" aria-hidden="true"></span> + </a> + </th> + <th>Role + <a class="text-danger" ng-click="ctrl.sortBy('role')" ng-class="{ 'hidden': !ctrl.sorting['role']}" > + <span class="glyphicon glyphicon-sort-by-alphabet pull-right" aria-hidden="true"></span> + </a> + <a class="text-danger" ng-click="ctrl.sortBy('role')" ng-class="{ 'hidden': ctrl.sorting['role']}" > + <span class="glyphicon glyphicon-sort-by-alphabet-alt pull-right" aria-hidden="true"></span> + </a> + </th> + <th>Mode + <a class="text-danger" ng-click="ctrl.sortBy('mode')" ng-class="{ 'hidden': !ctrl.sorting['mode'] }" > + <span class="glyphicon glyphicon-sort-by-alphabet pull-right" aria-hidden="true"></span> + </a> + <a class="text-danger" ng-click="ctrl.sortBy('mode')" ng-class="{ 'hidden': ctrl.sorting['mode'] }" > + <span class="glyphicon glyphicon-sort-by-alphabet-alt pull-right" aria-hidden="true"></span> + </a> + </th> <th ng-class="{ 'hidden': !auth.isAuthenticated }">Operation</th> </tr> </thead> @@ -67,9 +77,7 @@ <td>{{pod.mode}}</td> <td ng-class="{ 'hidden': !auth.isAuthenticated }"> <span class="podsTable-col"> - <a class="text-warning" title="Edit"> - <i class="fa fa-pencil-square-o"></i></a> - <a class="text-danger" ng-click="ctrl.openDeleteModal(pod.name)" title="Delete"> + <a class="text-danger" ng-click="ctrl.openDeleteModal(pod.name)" title="Delete" ng-class="{ 'hidden': !auth.isAuthenticated }"> <i class="fa fa-trash-o"></i></a> </span> </td> diff --git a/testapi/opnfv_testapi/ui/components/pods/podsController.js b/testapi/opnfv_testapi/ui/components/pods/podsController.js index c66873a..3b6ab97 100644 --- a/testapi/opnfv_testapi/ui/components/pods/podsController.js +++ b/testapi/opnfv_testapi/ui/components/pods/podsController.js @@ -21,7 +21,7 @@ PodsController.$inject = [ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert', - 'confirmModal' + 'confirmModal', 'keepState', 'sortService', '$timeout' ]; /** @@ -30,23 +30,41 @@ * through pods declared in TestAPI. */ function PodsController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl, - raiseAlert, confirmModal) { + raiseAlert, confirmModal, keepState, sortService, $timeout) { var ctrl = this; ctrl.url = testapiApiUrl + '/pods'; ctrl.checkBox = [] ctrl.checkBoxList = []; + ctrl.sorting = {}; ctrl.create = create; ctrl.listPods = listPods; ctrl.open = open; ctrl.filter = 'name' - ctrl.clearFilters = clearFilters; ctrl.openDeleteModal = openDeleteModal ctrl.openBatchDeleteModal = openBatchDeleteModal ctrl.openCreateModal = openCreateModal ctrl.podDelete = podDelete ctrl.batchDelete = batchDelete; ctrl.viewPod = viewPod + ctrl.sortBy = sortBy + ctrl.toastError = toastError + ctrl.toastSuccess = toastSuccess + + function toastError() { + ctrl.showError = true + $timeout(function(){ ctrl.showError = false;}, 3000); + } + + function toastSuccess() { + ctrl.showSuccess = true + $timeout(function(){ ctrl.showSuccess = false;}, 3000); + } + + function sortBy(field){ + ctrl.data.pods = sortService.sortFunction(ctrl.data.pods, field , ctrl.sorting[field] ) + ctrl.sorting[field]=!ctrl.sorting[field] + } /** * This is called when the date filter calendar is opened. It @@ -61,13 +79,6 @@ ctrl[openVar] = true; } - /** - * This function will clear all filters and update the results - * listing. - */ - function clearFilters() { - ctrl.listPods(); - } /** * This will contact the TestAPI to create a new pod. @@ -75,7 +86,6 @@ function create(pod) { ctrl.showError = false; ctrl.showSuccess = false; - console.log(pod); if(pod.name != ""){ var pods_url = ctrl.url; var body = { @@ -84,19 +94,21 @@ role: pod.role, details: pod.details }; - ctrl.podsRequest = - $http.post(pods_url, body).success(function (data) { - ctrl.showSuccess = true ; + ctrl.podsRequest = $http.post(pods_url, body) + + ctrl.podsRequest.success(function (data) { ctrl.success = "Create Success" + ctrl.toastSuccess() ctrl.listPods(); }).catch(function (data) { - ctrl.showError = true; - ctrl.error = "Error creating the new pod from server: " + data.statusText; + ctrl.error = data.statusText; + ctrl.toastError() }); + return ctrl.podsRequest } else{ - ctrl.showError = true; ctrl.error = 'Name is missing.' + ctrl.toastError() } } @@ -105,21 +117,33 @@ */ function listPods() { ctrl.showError = false; + var reqURL = ctrl.url; + if(ctrl.filterText!=undefined){ + reqURL = ctrl.url + "?name=" + ctrl.filterText + } + else if(keepState.filter.podFilter){ + for (var filter in keepState.filter.podFilter){ + reqURL = ctrl.url + '?' + filter + '=' + keepState.filter.podFilter[filter] + ctrl.filterText = keepState.filter.podFilter[filter] + } + } ctrl.podsRequest = - $http.get(ctrl.url).success(function (data) { + $http.get(reqURL).success(function (data) { ctrl.data = data; - // mapNametoRandom - }).error(function (error) { + ctrl.sortBy("name") + if(ctrl.filterText != undefined){ + keepState.filter.podFilter = { + 'name': ctrl.filterText + } + } + }).catch(function (data) { ctrl.data = null; - ctrl.showError = true; - ctrl.error = - 'Error retrieving pods from server: ' + - angular.toJson(error); + ctrl.error = data.statusText; + ctrl.toastError() }); } function viewPod(name){ - console.log('hello'); $state.go('pod', {'name':name}, {reload: true}); } /** @@ -129,12 +153,12 @@ function podDelete(podName){ var pods_url = ctrl.url + "/" + podName $http.delete(pods_url).success(function(){ - ctrl.showSuccess = true ; ctrl.success = "Delete Success" + ctrl.toastSuccess() ctrl.listPods(); }).catch(function (data) { - ctrl.showError = true; ctrl.error = data.statusText; + ctrl.toastError() }); } @@ -144,7 +168,6 @@ function batchDelete(){ var index; var checkedBox = []; - console.log(ctrl.checkBox) for(index in ctrl.checkBox){ if(!ctrl.showError){ if(ctrl.checkBox[index]){ @@ -160,7 +183,13 @@ * message */ function openBatchDeleteModal() { - confirmModal("Delete",ctrl.batchDelete); + var deleteObjects = [] + for(var index in ctrl.checkBox){ + if(ctrl.checkBox[index]){ + deleteObjects.push(ctrl.data.pods[index].name) + } + } + confirmModal("Delete", 'pods', ctrl.batchDelete, deleteObjects); } /** @@ -168,8 +197,7 @@ * message */ function openDeleteModal(name) { - console.log(name) - confirmModal("Delete", ctrl.podDelete, name); + confirmModal("Delete", 'pod', ctrl.podDelete, name); } /** @@ -192,22 +220,6 @@ }); } - // function openUpdateModal(podName){ - // $uibModal.open({ - // templateUrl: 'testapi-ui/components/pods/modals/createModal.html', - // controller: 'PodModalCtrl as PodModalCtrl', - // size: 'md', - // resolve: { - // data: function () { - // return { - // text: "Update", - // successHandler: ctrl.update, - // // pod: ctrl. - // }; - // } - // } - // }); - // } ctrl.listPods(); } @@ -249,9 +261,10 @@ * inputs. */ function confirm() { - $uibModalInstance.close(); if (angular.isDefined(ctrl.data.successHandler)) { - ctrl.data.successHandler(ctrl.pod); + ctrl.data.successHandler(ctrl.pod).success( function(data){ + $uibModalInstance.close(); + }) } } diff --git a/testapi/opnfv_testapi/ui/components/profile/profileController.js b/testapi/opnfv_testapi/ui/components/profile/profileController.js index 5dbdf7b..e34e745 100644 --- a/testapi/opnfv_testapi/ui/components/profile/profileController.js +++ b/testapi/opnfv_testapi/ui/components/profile/profileController.js @@ -35,7 +35,7 @@ ProfileController.$inject = [ '$scope', '$http', 'testapiApiUrl', 'PubKeys', - '$uibModal', 'raiseAlert', '$state' + '$uibModal', 'raiseAlert', '$state' , 'authenticate' ]; /** @@ -44,7 +44,7 @@ * account-specific information. */ function ProfileController($scope, $http, testapiApiUrl, - PubKeys, $uibModal, raiseAlert, $state) { + PubKeys, $uibModal, raiseAlert, $state, authenticate) { var ctrl = this; @@ -53,7 +53,7 @@ ctrl.openShowPubKeyModal = openShowPubKeyModal; // Must be authenticated to view this page. - if (!$scope.auth.isAuthenticated) { + if (!$scope.auth.isAuthenticated || !authenticate) { $state.go('home'); } @@ -115,8 +115,9 @@ ctrl.updatePubKeys(); }); } - - ctrl.authRequest = $scope.auth.doSignCheck().then(ctrl.updatePubKeys); + if(authenticate){ + ctrl.authRequest = $scope.auth.doSignCheck().then(ctrl.updatePubKeys); + } } angular diff --git a/testapi/opnfv_testapi/ui/components/projects/project/project.html b/testapi/opnfv_testapi/ui/components/projects/project/project.html index 2921bd9..2762fff 100644 --- a/testapi/opnfv_testapi/ui/components/projects/project/project.html +++ b/testapi/opnfv_testapi/ui/components/projects/project/project.html @@ -16,25 +16,11 @@ <div class="table-responsive"> <table class="table" ng-data="ctrl.data.pods"> <tbody> - <tr style="padding:9px"> - <td class="podsTableTd">Id :</td> - <td class="podsTableLeftTd">{{ctrl.data._id}}</td> + <tr ng-repeat-start="(index, detail) in ctrl.data_field" style="padding:9px"> + <td class="podsTableTd">{{detail | capitalize}} :</td> + <td width="85%" class="podsTableLeftTd">{{ctrl.data[index]}}</td> </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Name :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.name}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Owner :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.owner}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Created at :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data['creation_date']}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Description :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.description}}</td> + <tr ng-repeat-end=> </tr> </tbody> </table> diff --git a/testapi/opnfv_testapi/ui/components/projects/project/projectController.js b/testapi/opnfv_testapi/ui/components/projects/project/projectController.js index 78b805d..9dc9e27 100644 --- a/testapi/opnfv_testapi/ui/components/projects/project/projectController.js +++ b/testapi/opnfv_testapi/ui/components/projects/project/projectController.js @@ -21,7 +21,7 @@ ProjectController.$inject = [ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert', - 'confirmModal' + 'confirmModal', 'dataFieldService' ]; /** @@ -30,12 +30,13 @@ * through projects declared in TestAPI. */ function ProjectController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl, - raiseAlert, confirmModal) { + raiseAlert, confirmModal, dataFieldService) { var ctrl = this; ctrl.name = $state.params['name']; ctrl.url = testapiApiUrl + '/projects/' + ctrl.name; ctrl.loadDetails = loadDetails; + ctrl.data_field = {} /** * This will contact the TestAPI to get a listing of declared projects. @@ -45,6 +46,7 @@ ctrl.projectsRequest = $http.get(ctrl.url).success(function (data) { ctrl.data = data; + ctrl.data_field = dataFieldService.dataFunction(ctrl.data, ctrl.data_field) }).catch(function (error) { ctrl.data = null; ctrl.showError = true; diff --git a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCase.html b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCase.html index 70c026a..509f39a 100644 --- a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCase.html +++ b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCase.html @@ -3,69 +3,11 @@ <div class="table-responsive"> <table class="table" ng-data="ctrl.data"> <tbody> - <tr style="padding:9px"> - <td class="podsTableTd">Id :</td> - <td class="podsTableLeftTd">{{ctrl.data._id}}</td> + <tr ng-repeat-start="(index, detail) in ctrl.data_field" style="padding:9px"> + <td class="podsTableTd" >{{detail | capitalize}} :</td> + <td width="86%" class="podsTableLeftTd">{{ctrl.data[index]}}</td> </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Name :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.name}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Project :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.project_name}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Tier :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.tier}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Blocking :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.blocking}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">CI Loop :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.ci_loop}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Tags :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.tags}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Version :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.version}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Created at :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data['creation_date']}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Dependencies :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.dependencies}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Trust :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.trust}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Criteria :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.criteria}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Catalog Description :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.catalog_description}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">URL :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.url}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Run :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.run}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Description :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.description}}</td> + <tr ng-repeat-end=> </tr> </tbody> </table> diff --git a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCaseController.js b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCaseController.js index a38b633..6f93fc1 100644 --- a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCaseController.js +++ b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCase/testCaseController.js @@ -21,7 +21,7 @@ TestCaseController.$inject = [ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert', - 'confirmModal' + 'confirmModal', 'dataFieldService' ]; /** @@ -30,13 +30,14 @@ * through projects declared in TestAPI. */ function TestCaseController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl, - raiseAlert, confirmModal) { + raiseAlert, confirmModal, dataFieldService) { var ctrl = this; ctrl.name = $state.params['name']; ctrl.projectName = $state.params['project_name']; ctrl.url = testapiApiUrl + '/projects/' + ctrl.projectName + "/cases/" + ctrl.name; ctrl.loadDetails = loadDetails; + ctrl.data_field = {} /** * This will contact the TestAPI to get a listing of declared projects. @@ -46,6 +47,7 @@ ctrl.projectsRequest = $http.get(ctrl.url).success(function (data) { ctrl.data = data; + ctrl.data_field = dataFieldService.dataFunction(ctrl.data, ctrl.data_field) }).catch(function (error) { ctrl.data = null; ctrl.showError = true; diff --git a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html index 00dd0f1..04baa9c 100644 --- a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html +++ b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCases.html @@ -1,68 +1,64 @@ <div ng-controller="TestCasesController as testCasesCtrl" class="col-md-12"> -<div class="row podsTable" style="vertical-align:middle"> - <div class="col-sm-1 pull-right" ng-class="{ 'hidden': ! ((auth.projectNames.length>0) && - auth.isAuthenticated) }" > - <button type="button" class="btn btn-danger" ng-click="testCasesCtrl.openBatchDeleteModal()"> - <i class="fa fa-minus"></i> Delete</button> - </div> - <div class="col-sm-1 pull-right" ng-class="{ 'hidden': ! ((auth.projectNames.length>0) && - auth.isAuthenticated) }"> - <button type="button" class="btn btn-success" ng-click="testCasesCtrl.openCreateModal()"> - <i class="fa fa-plus"></i> Create</button> - </div> -</div> -<div class='clo-md-12'> - <div ng-show="testCasesCtrl.showError" class="alert alert-danger" role="alert"> - <span class="pull-right"> {{testCasesCtrl.error}}</span> - <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span> - </div> - <div ng-show="testCasesCtrl.showSuccess" class="alert alert-success" role="alert"> - <span class="pull-right"> {{testCasesCtrl.successMessage}}</span> - <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span> - </div> -</div> -<div class='clo-md-12' style="padding-right:0px"> - <div class="table-responsive"> - <table class="table table-bordered table-hover" ng-data="testCasesCtrl.data.testcases"> - <thead> - <tr style=" - text-align: center;"> - <th style="width: 1%;">Bulk Select</th> - <th style="width: 19%;">Name</th> - <th style="width: 20%;">Tier</th> - <th style="width: 20%;">Blocking</th> - <th style="width: 20%;">CI Loop</th> - <th style="width: 20%;" ng-class="{'hidden': ! ((auth.projectNames.length>0) && auth.isAuthenticated)}">Operations</th> - </tr> - </thead> - <tbody> - <tr ng-repeat-start="(index, testcase) in testCasesCtrl.data.testcases" style="padding:9px"> - <td> - <div class="text-center"> - <input type="checkbox" value="{{project.name}}" ng-model="testCasesCtrl.checkBox[index]" > - </div> - </td> - <td> - <a class="text-info" ng-click="testCasesCtrl.viewTestCase(testcase.name, testcase.project_name)"> - {{testcase.name}} - </a> - </td> - <td>{{ ctrl.data.tier}}</td> - <td>{{ctrl.data.blocking}}</td> - <td>{{ctrl.data.ci_loop}}</td> - <td ng-class="{'hidden': ! ((auth.projectNames.length>0) && auth.isAuthenticated)}"> - <span class="podsTable-col"> - <a class="text-warning" ng-click="testCasesCtrl.openUpdateTestModal(testcase.name)" title="Edit"> - <i class="fa fa-pencil-square-o"></i></a> - <a class="text-danger" ng-click="testCasesCtrl.openDeleteTestModal(testcase.name)" title="Delete"> - <i class="fa fa-trash-o"></i></a> - </span> - </td> - </tr> - <tr ng-repeat-end=> - </tr> - </tbody> - </table> - </div> -</div> -</div> + <div class="row podsTable" style="vertical-align:middle"> + <div class="col-sm-1 pull-right" ng-class="{ 'hidden': !((auth.projectNames.length>0) && + auth.isAuthenticated) && authenticate }" > + <button type="button" class="btn btn-danger" ng-click="testCasesCtrl.openBatchDeleteModal()"> + <i class="fa fa-minus"></i> Delete</button> + </div> + <div class="col-sm-1 pull-right" ng-class="{ 'hidden': ! ((auth.projectNames.length>0) && + auth.isAuthenticated) && authenticate }"> + <button type="button" class="btn btn-success" ng-click="testCasesCtrl.openCreateModal()"> + <i class="fa fa-plus"></i> Create</button> + </div> + </div> + <div ng-class="{'show': testCasesCtrl.showError}" id="toast" class="error"> + <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true" ></span> + {{testCasesCtrl.error}}</div> + <div ng-class="{'show': testCasesCtrl.showSuccess}" id="toast" class="success"> + <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> + {{testCasesCtrl.success}}</div> + <div class='clo-md-12' style="padding-right:0px"> + <div class="table-responsive"> + <table class="table table-bordered table-hover" ng-data="testCasesCtrl.data.testcases"> + <thead> + <tr style=" + text-align: center;"> + <th style="width: 1%;">Bulk Select</th> + <th style="width: 19%;">Name</th> + <th style="width: 20%;">Tier</th> + <th style="width: 20%;">Blocking</th> + <th style="width: 20%;">CI Loop</th> + <th style="width: 20%;" ng-class="{'hidden': ! ((auth.projectNames.length>0) && auth.isAuthenticated) && authenticate}">Operations</th> + </tr> + </thead> + <tbody> + <tr ng-repeat-start="(index, testcase) in testCasesCtrl.data.testcases" style="padding:9px"> + <td> + <div class="text-center"> + <input type="checkbox" value="{{project.name}}" ng-model="testCasesCtrl.checkBox[index]" > + </div> + </td> + <td> + <a class="text-info" ng-click="testCasesCtrl.viewTestCase(testcase.name, testcase.project_name)"> + {{testcase.name}} + </a> + </td> + <td>{{testcase.tier}}</td> + <td>{{testcase.blocking}}</td> + <td>{{testcase.ci_loop}}</td> + <td ng-class="{'hidden': ! ((auth.projectNames.length>0) && auth.isAuthenticated) && authenticate}"> + <span class="podsTable-col"> + <a class="text-warning" ng-click="testCasesCtrl.openUpdateTestModal(testcase.name)" title="Edit"> + <i class="fa fa-pencil-square-o"></i></a> + <a class="text-danger" ng-click="testCasesCtrl.openDeleteTestModal(testcase.name)" title="Delete"> + <i class="fa fa-trash-o"></i></a> + </span> + </td> + </tr> + <tr ng-repeat-end=> + </tr> + </tbody> + </table> + </div> + </div> + </div>
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js index 0045284..ea0498a 100644 --- a/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js +++ b/testapi/opnfv_testapi/ui/components/projects/project/testCases/testCasesController.js @@ -21,7 +21,7 @@ TestCasesController.$inject = [ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert', - 'confirmModal' + 'confirmModal', 'authenticate', '$timeout' ]; /** @@ -31,7 +31,7 @@ * in them. */ function TestCasesController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl, - raiseAlert, confirmModal) { + raiseAlert, confirmModal, authenticate, $timeout) { var ctrl = this; ctrl.loadDetails = loadDetails; ctrl.name = $state.params['name']; @@ -49,29 +49,40 @@ ctrl.checkBox = []; ctrl.checkBoxList = []; + ctrl.toastError = toastError + ctrl.toastSuccess = toastSuccess + + function toastError() { + ctrl.showError = true + $timeout(function(){ ctrl.showError = false;}, 3000); + } + + function toastSuccess() { + ctrl.showSuccess = true + $timeout(function(){ ctrl.showSuccess = false;}, 3000); + } /** * This will contact the TestAPI to create a new test case. */ function createTestCase(name, testcase) { - ctrl.showError = false; - ctrl.showSuccess = false; if(testcase.name != "" && testcase.name!=null){ var testCase_url = ctrl.requestUrl; - ctrl.testCasesRequest = - $http.post(testCase_url, testcase).success(function (data){ - ctrl.showSuccess = true ; - ctrl.successMessage = "Testcase is successfully created." + ctrl.testCasesRequest = $http.post(testCase_url, testcase) + ctrl.testCasesRequest.success(function (data){ + ctrl.success = "Testcase is successfully created." loadDetails(); + ctrl.toastSuccess() }) .catch(function (data) { - ctrl.showError = true; ctrl.error = data.statusText; + ctrl.toastError(); }); + return ctrl.testCasesRequest; } else{ - ctrl.showError = true; ctrl.error = 'Name is missing.' + ctrl.toastError(); } } @@ -84,7 +95,15 @@ * message */ function openBatchDeleteModal() { - confirmModal("Delete",ctrl.batchDelete); + var deleteObjects = [] + ctrl.checkBox.forEach(function(testcase, index){ + if(!ctrl.showError){ + if(testcase){ + deleteObjects.push(ctrl.data.testcases[index].name) + } + } + }); + confirmModal("Delete", 'testcases', ctrl.batchDelete, deleteObjects); } /** @@ -106,24 +125,23 @@ * This will contact the TestAPI to update an existing test case. */ function updateTestCase(name, testCase) { - ctrl.showError = false; - ctrl.showSuccess = false; if(testCase.name != ""){ var testCase_url = ctrl.requestUrl + '/' + name; - ctrl.testCasesRequest = - $http.put(testCase_url, testCase).success(function (data){ - ctrl.showSuccess = true ; - ctrl.successMessage = "Test case is successfully updated" + ctrl.testCasesRequest = $http.put(testCase_url, testCase) + ctrl.testCasesRequest.success(function (data){ + ctrl.success = "Test case is successfully updated" loadDetails(); + ctrl.toastSuccess(); }) .catch(function (data) { - ctrl.showError = true; ctrl.error = data.statusText; + ctrl.toastError() }); + return ctrl.testCasesRequest; } else{ - ctrl.showError = true; ctrl.error = 'Name is missing.' + ctrl.toastError() } } @@ -131,16 +149,14 @@ * This will contact the TestAPI to delete an existing test case. */ function deleteTestCase(name) { - ctrl.showError = false; - ctrl.showSuccess = false; ctrl.testCasesRequest = $http.delete(ctrl.requestUrl+"/"+name).success(function (data) { loadDetails(); - ctrl.showSuccess = true ; - ctrl.successMessage = "Test case is successfully deleted" + ctrl.success = "Test case is successfully deleted"; + ctrl.toastSuccess(); }).catch(function (error) { - ctrl.showError = true; - ctrl.error = data.statusText; + ctrl.error = error.statusText; + ctrl.toastError(); }); } @@ -149,7 +165,7 @@ * message */ function openDeleteTestModal(name) { - confirmModal("Delete", ctrl.deleteTestCase, name); + confirmModal("Delete", 'testcases', ctrl.deleteTestCase, name); } /** @@ -210,8 +226,8 @@ ctrl.data = data; }).catch(function (error) { ctrl.data = null; - ctrl.showError = true; ctrl.error = error.statusText; + ctrl.toastError() }); } ctrl.loadDetails(); @@ -244,12 +260,13 @@ {label: 'blocking', type: 'text', required: false}, {label: 'criteria', type: 'text', required: false}, {label: 'domains', type: 'text', required: false}, + {label: 'ci_loop', type: 'text', required: false}, {label: 'catalog_description', type: 'text', required: false} ]; ctrl.testcase = {name : null, description : null,version : null, tier : null, tags : null, run : null, dependencies : null, trust : null, url : null, blocking : null, - criteria : null, domains : null, catalog_description : null}; + criteria : null, domains : null, ci_loop: null, catalog_description : null}; if(ctrl.data.text=="Update"){ ctrl.testcase = ctrl.data.testCase @@ -262,9 +279,15 @@ * inputs. */ function confirm() { - $uibModalInstance.close(); if (angular.isDefined(ctrl.data.successHandler)) { - ctrl.data.successHandler(ctrl.name, ctrl.testcase); + if(ctrl.testcase.name){ + ctrl.data.successHandler(ctrl.name, ctrl.testcase).success( function(){ + $uibModalInstance.close(); + }) + } + else{ + ctrl.data.successHandler(ctrl.name, ctrl.testcase) + } } } diff --git a/testapi/opnfv_testapi/ui/components/projects/projects.html b/testapi/opnfv_testapi/ui/components/projects/projects.html index 8a27a57..3098aa2 100644 --- a/testapi/opnfv_testapi/ui/components/projects/projects.html +++ b/testapi/opnfv_testapi/ui/components/projects/projects.html @@ -2,13 +2,13 @@ <div class="row" style="margin-bottom:24px;"></div> <div class="row podsTable" style="vertical-align:middle"> - <div class="col-sm-1 pull-right" ng-class="{ 'hidden': ! ((auth.projectNames.length>0) && - auth.isAuthenticated) }" > + <div class="col-sm-1 pull-right" ng-class="{ 'hidden': !((auth.projectNames.length>0) && + auth.isAuthenticated) && authenticate}" > <button type="button" class="btn btn-danger" ng-click="ctrl.openBatchDeleteModal()"> <i class="fa fa-minus"></i> Delete</button> </div> <div class="col-sm-1 pull-right" ng-class="{ 'hidden': ! ((auth.projectNames.length>0) && - auth.isAuthenticated) }"> + auth.isAuthenticated) && authenticate}"> <button type="button" class="btn btn-success" ng-click="ctrl.openCreateModal()"> <i class="fa fa-plus"></i> Create</button> </div> @@ -18,19 +18,15 @@ </div> <div class="col-sm-3 pull-right"> <span style="margin-top:6px">Search: </span> - <input type="text" class="form-control search" ng-Model="ctrl.filterText" style="width:80%;" placeholder="Search By Name"> - </div> -</div> -<div class='clo-md-12'> - <div ng-show="ctrl.showError" class="alert alert-danger" role="alert"> - <span class="pull-right"> {{ctrl.error}}</span> - <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span> - </div> - <div ng-show="ctrl.showCreateSuccess" class="alert alert-success" role="alert"> - <span class="pull-right"> {{ctrl.success}}</span> - <span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span> + <input type="text" class="form-control search" ng-enter="ctrl.listProjects()" ng-Model="ctrl.filterText" style="width:80%;" placeholder="Search By Name"> </div> </div> +<div ng-class="{'show': ctrl.showError}" id="toast" class="error"> + <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true" ></span> + {{ctrl.error}}</div> +<div ng-class="{'show': ctrl.showSuccess}" id="toast" class="success"> + <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> + {{ctrl.success}}</div> <div class='clo-md-12' style="padding-right:0px"> <div class="table-responsive"> <table class="table table-bordered table-hover" ng-data="ctrl.data.projects"> @@ -38,9 +34,16 @@ <tr style=" text-align: center;"> <th style="width: 1%;">Bulk Select</th> - <th style="width: 19%;">Name</th> + <th style="width: 19%;">Name + <a class="text-danger" ng-click="ctrl.sortByName()" ng-class="{ 'hidden': !ctrl.sortName }" > + <span class="glyphicon glyphicon-sort-by-alphabet pull-right" aria-hidden="true"></span> + </a> + <a class="text-danger" ng-click="ctrl.sortByName()" ng-class="{ 'hidden': ctrl.sortName }" > + <span class="glyphicon glyphicon-sort-by-alphabet-alt pull-right" aria-hidden="true"></span> + </a> + </th> <th style="width: 70%;">Description</th> - <th style="width: 10%;" ng-class="{'hidden': ! ((auth.projectNames.length>0) && auth.isAuthenticated)}">Operations</th> + <th style="width: 10%;" ng-class="{'hidden': ! ((auth.projectNames.length>0) && auth.isAuthenticated) && authenticate}">Operations</th> </tr> </thead> <tbody> @@ -52,7 +55,7 @@ </td> <td><a class="text-info" ng-click="ctrl.viewProject(project.name)">{{project.name}}</a></td> <td>{{project.description}}</td> - <td ng-class="{'hidden': ! ((auth.projectNames.length>0) && auth.isAuthenticated)}"> + <td ng-class="{'hidden': ! ((auth.projectNames.length>0) && auth.isAuthenticated) && authenticate}"> <span class="podsTable-col"> <a class="text-warning" ng-click="ctrl.openUpdateModal(project.name)" title="Edit" > <i class="fa fa-pencil-square-o"></i></a> diff --git a/testapi/opnfv_testapi/ui/components/projects/projectsController.js b/testapi/opnfv_testapi/ui/components/projects/projectsController.js index 38764ea..42100bd 100644 --- a/testapi/opnfv_testapi/ui/components/projects/projectsController.js +++ b/testapi/opnfv_testapi/ui/components/projects/projectsController.js @@ -21,7 +21,7 @@ ProjectsController.$inject = [ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl', - 'raiseAlert', 'confirmModal' + 'raiseAlert', 'confirmModal', 'authenticate', 'keepState', 'sortService', '$timeout' ]; /** @@ -30,7 +30,7 @@ * through projects declared in TestAPI. */ function ProjectsController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl, - raiseAlert, confirmModal) { + raiseAlert, confirmModal, authenticate, keepState, sortService, $timeout) { var ctrl = this; ctrl.url = testapiApiUrl + '/projects'; @@ -44,33 +44,53 @@ ctrl.openBatchDeleteModal = openBatchDeleteModal; ctrl.projectDelete = projectDelete; ctrl.batchDelete = batchDelete; + ctrl.sortByName = sortByName ctrl.checkBox = []; ctrl.checkBoxList = []; ctrl.name = ''; ctrl.details = ''; - ctrl.filterText=''; + ctrl.ascending = false; + ctrl.toastError = toastError + ctrl.toastSuccess = toastSuccess + + function toastError() { + ctrl.showError = true + $timeout(function(){ ctrl.showError = false;}, 7000); + } + + function toastSuccess() { + ctrl.showSuccess = true + $timeout(function(){ ctrl.showSuccess = false;}, 7000); + } /** * This will contact the TestAPI to create a new project. */ function create(project) { - ctrl.showError = false; - ctrl.showCreateSuccess = false; var projects_url = ctrl.url; var body = { name: project.name, description: project.description }; - ctrl.projectsRequest = - $http.post(projects_url, body).success(function (data){ - ctrl.showCreateSuccess = true ; - ctrl.success = "Project is successfully created." + ctrl.projectsRequest = $http.post(projects_url, body) + ctrl.projectsRequest.success(function (data){ + ctrl.success = "Project is successfully created."; ctrl.listProjects(); + ctrl.toastSuccess(); + ctrl.request = true; }).catch(function (data) { - ctrl.showError = true; ctrl.error = data.statusText; + ctrl.toastError(); + ctrl.request = false; }); + + return ctrl.projectsRequest + } + + function sortByName(){ + ctrl.data.projects = sortService.sortFunction(ctrl.data.projects, 'name', ctrl.ascending) + ctrl.ascending = !ctrl.ascending } /** @@ -129,16 +149,17 @@ ctrl.showError = false; ctrl.showSuccess = false; var projectUrl = ctrl.url + '/' + name; - ctrl.testCasesRequest = - $http.put(projectUrl, project).success(function (data){ - ctrl.showSuccess = true ; + ctrl.projectRequest = $http.put(projectUrl, project) + ctrl.projectRequest.success(function (data){ ctrl.success = "Project is successfully updated." - listProjects(); + ctrl.listProjects(); + ctrl.toastSuccess(); }) .catch(function (data) { - ctrl.showError = true; ctrl.error = data.statusText; + ctrl.toastError(); }); + return ctrl.projectRequest } /** @@ -148,17 +169,28 @@ ctrl.showError = false; var content_url = ctrl.url + '?'; var filterText = ctrl.filterText; - if(filterText != ''){ + if(filterText != undefined){ content_url = content_url + 'name=' + filterText; } + else if(keepState.filter.projectFilter){ + for (var filter in keepState.filter.projectFilter){ + content_url = content_url + filter + '=' + keepState.filter.projectFilter[filter] + ctrl.filterText = keepState.filter.projectFilter[filter] + } + } ctrl.resultsRequest = $http.get(content_url).success(function (data) { ctrl.data = data; + if(ctrl.filterText != undefined){ + keepState.filter.projectFilter = { + 'name': ctrl.filterText + } + } }).catch(function (data) { ctrl.data = null; - ctrl.showError = true; ctrl.error = data.statusText; + ctrl.toastError(); }); } @@ -173,13 +205,12 @@ function projectDelete(projectName){ var projectUrl = ctrl.url + "/" + projectName $http.delete(projectUrl).success(function(){ - ctrl.showSuccess = true ; ctrl.success = "Projects is successfully deleted" + ctrl.toastSuccess(); ctrl.listProjects(); }).catch(function (data) { - ctrl.showError = true; - ctrl.showSuccess = false; ctrl.error = data.statusText; + ctrl.toastError(); }); } @@ -204,7 +235,15 @@ * message */ function openBatchDeleteModal() { - confirmModal("Delete",ctrl.batchDelete); + var deleteObjects = [] + ctrl.checkBox.forEach(function(project, index){ + if(!ctrl.showError){ + if(project){ + deleteObjects.push(ctrl.data.projects[index].name) + } + } + }); + confirmModal("Delete", 'projects', ctrl.batchDelete, deleteObjects); } /** @@ -212,7 +251,7 @@ * message */ function openDeleteModal(name) { - confirmModal("Delete", ctrl.projectDelete, name); + confirmModal("Delete",'projects', ctrl.projectDelete, name); } ctrl.listProjects(); @@ -252,11 +291,15 @@ function confirm() { if (angular.isDefined(ctrl.data.successHandler)) { if(ctrl.project.name != ""){ - $uibModalInstance.close(); + var success = false; if(ctrl.data.project){ - ctrl.data.successHandler(ctrl.projectName, ctrl.project); + ctrl.data.successHandler(ctrl.projectName, ctrl.project).success(function (data){ + $uibModalInstance.close(); + }) }else{ - ctrl.data.successHandler(ctrl.project); + ctrl.data.successHandler(ctrl.project).success(function (data){ + $uibModalInstance.close(); + }) } }else{ ctrl.showCreateError = true; diff --git a/testapi/opnfv_testapi/ui/components/results/result/result.html b/testapi/opnfv_testapi/ui/components/results/result/result.html index b435dce..041f244 100644 --- a/testapi/opnfv_testapi/ui/components/results/result/result.html +++ b/testapi/opnfv_testapi/ui/components/results/result/result.html @@ -3,100 +3,16 @@ <div class="table-responsive"> <table class="table" ng-data="ctrl.data.pods"> <tbody> - <tr style="padding:9px"> - <td class="podsTableTd">Id :</td> - <td class="podsTableLeftTd">{{ctrl.data._id}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Pod Name:</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.pod_name}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Project Name:</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.project_name}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Case Name :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.case_name}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Installer :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.installer}}</td> + <tr ng-repeat-start="(index, detail) in ctrl.data_field" style="padding:9px"> + <td class="podsTableTd">{{detail | capitalize}} :</td> + <td width="90%" class="podsTableLeftTd">{{ctrl.data[index]}}</td> </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Version :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.version}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Scenario :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.scenario}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Build tag :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data['build_tag']}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Criteria :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.criteria}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Start Date:</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.start_date}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Stop Date :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.stop_date}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Trust Indicator :</td> - <td width="90%" class="podsTableLeftTd"> - <a ng-click="ctrl.showTrustIndicator()"> - <p ng-if="ctrl.trust_indicator">Hide</p> - <p ng-if="!ctrl.trust_indicator">Show</p> - </a> - <table class="table" ng-class="{'hidden' : !ctrl.trust_indicator}" style="margin:10px"> - <tbody> - <tr style="padding:9px"></tr> - <tr style="padding:9px" > - <td class="podsTableTd">Current :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.trust_indicator.current}}</td> - </tr> - <tr style="padding:9px" > - <td class="podsTableTd">Histories :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.trust_indicator.histories}}</td> - </tr> - </tbody> - </table> - </td> + <tr ng-repeat-end=> </tr> <tr style="padding:9px"> <td class="podsTableTd">Details :</td> <td width="90%" class="podsTableLeftTd"> - <a ng-click="ctrl.showDetails()"> - <p ng-if="ctrl.details">Hide</p> - <p ng-if="!ctrl.details">Show</p> - </a> - <table class="table" ng-class="{'hidden' : !ctrl.details}" style="margin:10px"> - <tbody> - <tr style="padding:9px"></tr> - <tr style="padding:9px"> - <td class="podsTableTd">Failures :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.details.failures}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Details :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.details.errors}}</td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">Stream :</td> - <td width="90%" class="podsTableLeftTd"><p>{{ctrl.data.details.stream}}</p></td> - </tr> - <tr style="padding:9px"> - <td class="podsTableTd">TestsRun :</td> - <td width="90%" class="podsTableLeftTd"><p>{{ctrl.data.details.testsRun}}</p></td> - </tr> - </tbody> - </table> + <json-tree object="ctrl.json.object" root-name="object" start-expanded="true"></json-tree> </td> </tr> </tbody> diff --git a/testapi/opnfv_testapi/ui/components/results/result/resultController.js b/testapi/opnfv_testapi/ui/components/results/result/resultController.js index 028e5d8..2726704 100644 --- a/testapi/opnfv_testapi/ui/components/results/result/resultController.js +++ b/testapi/opnfv_testapi/ui/components/results/result/resultController.js @@ -21,7 +21,7 @@ ResultController.$inject = [ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert', - 'confirmModal' + 'confirmModal', 'dataFieldService' ]; /** @@ -30,13 +30,16 @@ * through result declared in TestAPI. */ function ResultController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl, - raiseAlert, confirmModal) { + raiseAlert, confirmModal, dataFieldService) { var ctrl = this; ctrl.url = testapiApiUrl + '/results'; ctrl._id = $state.params['_id']; ctrl.loadDetails = loadDetails - ctrl.showTrustIndicator = showTrustIndicator - ctrl.showDetails = showDetails + ctrl.data_field = {} + + ctrl.json = {}; + ctrl.json.string = '{"id": ""}'; + ctrl.json.object = JSON.parse(ctrl.json.string); /** *Contact the testapi and retrevie the result details @@ -47,6 +50,10 @@ ctrl.podsRequest = $http.get(resultUrl).success(function (data) { ctrl.data = data; + ctrl.object=JSON.stringify(ctrl.data.details) + ctrl.json.object = JSON.parse(ctrl.object) + delete ctrl.data.details; + ctrl.data_field = dataFieldService.dataFunction(ctrl.data, ctrl.data_field) }).catch(function (error) { ctrl.data = null; ctrl.showError = true; @@ -54,21 +61,6 @@ }); } - function showTrustIndicator(){ - if(ctrl.trust_indicator){ - ctrl.trust_indicator = false - }else{ - ctrl.trust_indicator = true - } - } - - function showDetails(){ - if(ctrl.details){ - ctrl.details = false - }else{ - ctrl.details = true - } - } ctrl.loadDetails(); } })();
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/results/results.html b/testapi/opnfv_testapi/ui/components/results/results.html index 7809065..a433525 100644 --- a/testapi/opnfv_testapi/ui/components/results/results.html +++ b/testapi/opnfv_testapi/ui/components/results/results.html @@ -1,22 +1,5 @@ <h3>{{ctrl.pageHeader}}</h3> <p>{{ctrl.pageParagraph}}</p> -<form class="form-inline" ng-show="ctrl.isUserResults"> -<h4>Upload Results</h4> -<div class="form-group col-m-3"> - <input class="form-contrl btn btn-default" type = "file" file-model = "resultFile"/> -</div> -<div class="checkbox col-m-1"> - <label> - <input type="checkbox" ng-model="ctrl.isPublic">public - </label> -</div> -<div class="form-group col-m-3"> - <button class="btn btn-primary" ng-click = "ctrl.uploadFile()">upload result</button> -</div> -<div> -<lable>{{ctrl.uploadState}}</label> -</div> -</form> <div class="row" style="margin-bottom:24px;"></div> <div class="result-filters" style="border-top: none;"> <div class="row podTable" style="vertical-align:middle"> @@ -31,13 +14,17 @@ </div> <div class="col-sm-2 pull-right" ng-class="{'hidden': ctrl.filter=='start_date' || ctrl.filter=='end_date'}"> <span style="margin-top:6px">Search: </span> - <input type="text" class="form-control search" style="display:inline;width:105px;padding-left:6px;" + <input list="filter" ng-enter="ctrl.filterList()" name="filter" class="form-control search" style="display:inline;width:105px;padding-left:6px;" ng-Model="ctrl.filterText" placeholder="Search String"> + <datalist id="filter" ng-class="{ 'hidden' : ctrl.filterOption.length<0}"> + <option ng-repeat="(index, filterValue) in ctrl.filterOption " value="{{filterValue}}">{{filterValue}}</option> + </datalist> </div> <div class="col-sm-3 pull-right" style="width:20%" ng-class="{'hidden': ctrl.filter!='start_date'}"> <span style="margin-top:6px">Start Date: </span> <p class="input-group" style="width:48%;display:inline-flex;"> <input type="text" class="form-control" + ng-enter="ctrl.filterList()" uib-datepicker-popup="{{ctrl.format}}" ng-model="ctrl.filterText" is-open="ctrl.startOpen" close-text="Close" /> @@ -52,6 +39,7 @@ <span style="margin-top:6px">End Date: </span> <p class="input-group" style="width:48%;display:inline-flex;"> <input type="text" class="form-control" + ng-enter="ctrl.filterList()" uib-datepicker-popup="{{ctrl.format}}" ng-model="ctrl.filterText" is-open="ctrl.endOpen" close-text="Close" /> @@ -64,7 +52,7 @@ </div> <div class="col-md-2 row pull-right" style="width: 20%;"> <span style="margin-top:6px">Filter: </span> - <select ng-model="ctrl.filter" class="form-control" style="display:inline; width:150px;"> + <select ng-model="ctrl.filter" ng-change="ctrl.encodeFilter()" class="form-control" style="display:inline; width:150px;"> <option value="pod" ng-disabled="ctrl.testFilter('pod')" >Pod Name</option> <option value="project" ng-disabled="ctrl.testFilter('project')" >Project Name</option> <option value="case" ng-disabled="ctrl.testFilter('case')">Case Name</option> @@ -79,9 +67,9 @@ </div> <div class='filter-box'> - <div class='filter-tag' ng-repeat="(key, tag) in ctrl.tagArray"> + <div class='filter-tag col-md-1' ng-repeat="(key, tag) in ctrl.tagArray" style="background-color: #f5f5f5;border: 1px solid #e3e3e3;/* border: 1px; */margin-top: 3px;padding: 4px;margin-left: 15px;width: 13%;"> {{key}} : {{tag}} - <div class='delete-tag' ng-click='ctrl.deleteTag(key)'> + <div class='delete-tag btn btn-danger btn-xs' ng-click='ctrl.deleteTag(key)'> × </div> </div> @@ -104,13 +92,12 @@ <th>Scenario</th> <th>Criteria</th> <th>Start Date</th> - <th>Stop Date</th> </tr> </thead> <tbody> <tr ng-repeat-start="(index, result) in ctrl.data.results"> - <td><a ng-click="ctrl.viewResult(result._id)">{{ result._id }}</a></td> + <td><a ng-click="ctrl.viewResult(result._id)">{{ result._id.substr(-8) }}</a></td> <td>{{ result.pod_name }}</td> <td>{{ result.project_name }}</td> <td>{{ result.case_name }}</td> @@ -118,8 +105,7 @@ <td>{{ result.version }}</td> <td>{{ result.scenario }}</td> <td>{{ result.criteria }}</td> - <td>{{ result.start_date }}</td> - <td>{{ result.stop_date }}</td> + <td>{{ result.start_date}}</td> </tr> <tr ng-repeat-end=> </tr> @@ -145,4 +131,4 @@ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <span class="sr-only">Error:</span> {{ctrl.error}} -</div> +</div>
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/results/resultsController.js b/testapi/opnfv_testapi/ui/components/results/resultsController.js index 55bf0ba..13ead6e 100644 --- a/testapi/opnfv_testapi/ui/components/results/resultsController.js +++ b/testapi/opnfv_testapi/ui/components/results/resultsController.js @@ -38,7 +38,8 @@ }]); ResultsController.$inject = [ - '$scope', '$http', '$filter', '$state', 'testapiApiUrl','raiseAlert' + '$scope', '$http', '$filter', '$state', 'testapiApiUrl', 'raiseAlert', + 'keepState' ]; /** @@ -47,24 +48,21 @@ * a listing of community uploaded results. */ function ResultsController($scope, $http, $filter, $state, testapiApiUrl, - raiseAlert) { + raiseAlert, keepState) { var ctrl = this; - ctrl.uploadFile=uploadFile; ctrl.open = open; ctrl.clearFilters = clearFilters; - ctrl.associateMeta = associateMeta; - ctrl.getVersionList = getVersionList; - ctrl.getUserProducts = getUserProducts; - ctrl.associateProductVersion = associateProductVersion; - ctrl.getProductVersions = getProductVersions; - ctrl.prepVersionEdit = prepVersionEdit; ctrl.deleteTag = deleteTag; ctrl.filterList= filterList; ctrl.testFilter = testFilter ctrl.viewResult = viewResult; + ctrl.filter = "pod" + ctrl.filterValue = "pod_name" + ctrl.encodeFilter = encodeFilter ctrl.tagArray = {} + ctrl.filterOption=[] /** Mappings of Interop WG components to marketing program names. */ ctrl.targetMappings = { @@ -102,12 +100,12 @@ /** Check to see if this page should display user-specific results. */ // ctrl.isUserResults = $state.current.name === 'userResults'; // need auth to browse - ctrl.isUserResults = $state.current.name === 'userResults'; + // ctrl.isUserResults = $state.current.name === 'userResults'; - // Should only be on user-results-page if authenticated. - if (ctrl.isUserResults && !$scope.auth.isAuthenticated) { - $state.go('home'); - } + // // Should only be on user-results-page if authenticated. + // if (ctrl.isUserResults && !$scope.auth.isAuthenticated) { + // $state.go('home'); + // } ctrl.pageHeader = "Test Results" @@ -116,16 +114,85 @@ 'The most recently uploaded community test results are listed ' + 'here.'; - ctrl.uploadState = ''; + // ctrl.uploadState = ''; ctrl.isPublic = false; - if (ctrl.isUserResults) { - ctrl.authRequest = $scope.auth.doSignCheck() - .then(ctrl.filterList); - // ctrl.getUserProducts(); - } else { - ctrl.filterList(); + // if (ctrl.isUserResults) { + // ctrl.authRequest = $scope.auth.doSignCheck() + // .then(ctrl.filterList); + // // ctrl.getUserProducts(); + // } else { + // ctrl.filterList(); + // } + + function encodeFilter(){ + ctrl.filterText = '' + ctrl.filterOption=[] + if(ctrl.filter=="pod" || ctrl.filter=="project" || ctrl.filter=="scenario"){ + var reqURL = testapiApiUrl +"/" + ctrl.filter + "s" + ctrl.datasRequest = + $http.get(reqURL).success(function (data) { + ctrl.filterData = data; + for(var index in ctrl.filterData[ctrl.filter + "s"]){ + if( ctrl.filterOption.indexOf(ctrl.filterData[ctrl.filter + "s"][index]["name"]) < 0){ + ctrl.filterOption.push(ctrl.filterData[ctrl.filter + "s"][index]["name"]) + } + } + }).catch(function (data) { + ctrl.data = null; + ctrl.showError = true; + ctrl.error = data.statusText; + }); + + } + else if(ctrl.filter=="case"){ + if("project" in ctrl.tagArray){ + var reqURL = testapiApiUrl +"/projects/"+ctrl.tagArray["project"]+"/cases" + ctrl.dataRequest = + $http.get(reqURL).success(function (data) { + ctrl.filterData = data; + for(var index in ctrl.filterData.testcases){ + if( ctrl.filterOption.indexOf(ctrl.filterData.testcases[index]["name"]) < 0){ + ctrl.filterOption.push(ctrl.filterData.testcases[index]["name"]) + } + } + }).catch(function (data) { + ctrl.data = null; + ctrl.showError = true; + ctrl.error = data.statusText; + }); + + } + else{ + var reqURL = testapiApiUrl +"/projects" + ctrl.dataRequest = + $http.get(reqURL).success(function (data) { + ctrl.projectsData = data; + for(var indexP in ctrl.projectsData.projects){ + reqURL = testapiApiUrl +"/projects/" + ctrl.projectsData.projects[indexP]["name"] +"/cases" + ctrl.datasRequest = + $http.get(reqURL).success(function (data) { + ctrl.filterData = data; + for(var index in ctrl.filterData.testcases){ + if( ctrl.filterOption.indexOf(ctrl.filterData.testcases[index]["name"]) < 0){ + ctrl.filterOption.push(ctrl.filterData.testcases[index]["name"]) + } + } + }).catch(function (data) { + ctrl.data = null; + ctrl.showError = true; + ctrl.error = data.statusText; + }); + } + }).catch(function (data) { + ctrl.data = null; + ctrl.showError = true; + ctrl.error = data.statusText; + }); + } + + } } function viewResult(_id){ @@ -146,44 +213,22 @@ return false; } - - function uploadFileToUrl(file, uploadUrl){ - var fd = new FormData(); - fd.append('file', file); - fd.append('public', ctrl.isPublic) - - $http.post(uploadUrl, fd, { - transformRequest: angular.identity, - headers: {'Content-Type': undefined} - }) - - .success(function(data){ - var id = data.href.substr(data.href.lastIndexOf('/')+1); - ctrl.uploadState = "Upload succeed. Result id is " + id; - ctrl.filterList(); - }) - - .error(function(data, status){ - ctrl.uploadState = "Upload failed. Error code is " + status; - }); - } - - function uploadFile(){ - var file = $scope.resultFile; - console.log('file is ' ); - console.dir(file); - - var uploadUrl = testapiApiUrl + "/results/upload"; - uploadFileToUrl(file, uploadUrl); - }; - /** * This will contact the TestAPI API to get a listing of test run * results. */ function filterList(){ - if(ctrl.filter && ctrl.filterText!=""){ + if(ctrl.filter && ctrl.filterText!="" && ctrl.filterText!=undefined){ ctrl.tagArray[ctrl.filter] = ctrl.filterText; + if(!keepState.filter.resultFilter){ + keepState.filter.resultFilter = {} + } + keepState.filter.resultFilter[ctrl.filter] = ctrl.filterText + } + else if(Object.keys(ctrl.tagArray).length==0){ + if(keepState.filter.resultFilter){ + ctrl.tagArray = keepState.filter.resultFilter + } } ctrl.showError = false; var content_url = testapiApiUrl + '/results' + @@ -214,6 +259,7 @@ ctrl.data = data; ctrl.totalItems = ctrl.data.pagination.total_pages * ctrl.itemsPerPage; ctrl.currentPage = ctrl.data.pagination.current_page; + ctrl.encodeFilter(); }).error(function (error) { ctrl.data = null; ctrl.totalItems = 0; @@ -224,8 +270,10 @@ }); ctrl.filterText = '' } + ctrl.filterList(); + /** * This is called when the date filter calendar is opened. It * does some event handling, and sets a scope variable so the UI @@ -246,160 +294,8 @@ function clearFilters() { ctrl.tagArray = {} ctrl.filter = undefined + keepState.filter.resultFilter = {} ctrl.filterList(); } - - /** - * This will send an API request in order to associate a metadata - * key-value pair with the given testId - * @param {Number} index - index of the test object in the results list - * @param {String} key - metadata key - * @param {String} value - metadata value - */ - function associateMeta(index, key, value) { - var testId = ctrl.data.results[index].id; - var metaUrl = [ - testapiApiUrl, '/results/', testId, '/meta/', key - ].join(''); - - var editFlag = key + 'Edit'; - if (value) { - ctrl.associateRequest = $http.post(metaUrl, value) - .success(function () { - ctrl.data.results[index][editFlag] = false; - }).error(function (error) { - raiseAlert('danger', error.title, error.detail); - }); - } - else { - ctrl.unassociateRequest = $http.delete(metaUrl) - .success(function () { - ctrl.data.results[index][editFlag] = false; - }).error(function (error) { - if (error.code == 404) { - // Key doesn't exist, so count it as a success, - // and don't raise an alert. - ctrl.data.results[index][editFlag] = false; - } - else { - raiseAlert('danger', error.title, error.detail); - } - }); - } - } - - /** - * Retrieve an array of available capability files from the TestAPI - * API server, sort this array reverse-alphabetically, and store it in - * a scoped variable. - * Sample API return array: ["2015.03.json", "2015.04.json"] - */ - function getVersionList() { - if (ctrl.versionList) { - return; - } - var content_url = testapiApiUrl + '/guidelines'; - ctrl.versionsRequest = - $http.get(content_url).success(function (data) { - ctrl.versionList = data.sort().reverse(); - }).error(function (error) { - raiseAlert('danger', error.title, - 'Unable to retrieve version list'); - }); - } - - /** - * Get products user has management rights to or all products depending - * on the passed in parameter value. - */ - function getUserProducts() { - if (ctrl.products) { - return; - } - var contentUrl = testapiApiUrl + '/products'; - ctrl.productsRequest = - $http.get(contentUrl).success(function (data) { - ctrl.products = {}; - angular.forEach(data.products, function(prod) { - if (prod.can_manage) { - ctrl.products[prod.id] = prod; - } - }); - }).error(function (error) { - ctrl.products = null; - ctrl.showError = true; - ctrl.error = - 'Error retrieving Products listing from server: ' + - angular.toJson(error); - }); - } - - /** - * Send a PUT request to the API server to associate a product with - * a test result. - */ - function associateProductVersion(result) { - var verId = (result.selectedVersion ? - result.selectedVersion.id : null); - var testId = result.id; - var url = testapiApiUrl + '/results/' + testId; - ctrl.associateRequest = $http.put(url, {'product_version_id': - verId}) - .success(function (data) { - result.product_version = result.selectedVersion; - if (result.selectedVersion) { - result.product_version.product_info = - result.selectedProduct; - } - result.productEdit = false; - }).error(function (error) { - raiseAlert('danger', error.title, error.detail); - }); - } - - /** - * Get all versions for a product. - */ - function getProductVersions(result) { - if (!result.selectedProduct) { - result.productVersions = []; - result.selectedVersion = null; - return; - } - - var url = testapiApiUrl + '/products/' + - result.selectedProduct.id + '/versions'; - ctrl.getVersionsRequest = $http.get(url) - .success(function (data) { - result.productVersions = data; - - // If the test result isn't already associated to a - // version, default it to the null version. - if (!result.product_version) { - angular.forEach(data, function(ver) { - if (!ver.version) { - result.selectedVersion = ver; - } - }); - } - }).error(function (error) { - raiseAlert('danger', error.title, error.detail); - }); - } - - /** - * Instantiate variables needed for editing product/version - * associations. - */ - function prepVersionEdit(result) { - result.productEdit = true; - if (result.product_version) { - result.selectedProduct = - ctrl.products[result.product_version.product_info.id]; - } - result.selectedVersion = result.product_version; - ctrl.getProductVersions(result); - } - } -})(); +})();
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/customModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/customModal.html new file mode 100644 index 0000000..4225749 --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/customModal.html @@ -0,0 +1,38 @@ +<div class="ball" style="padding:5px;"> + <div class="modal-body"> + <div class="form-horizontal"> + <fieldset> + <div class="form-group"> + <legend>{{customModalCtrl.data.text}}</legend> + <div class="row"> + <div class="update-project"> + <label for="cpid" class="control-label col-sm-2">Custom: </label> + <table cellpadding="0" cellspacing="0"> + <tbody> + <tr> + <td> + <div class="col-sm-12"> + <input type="text" class="form-control" ng-model="customModalCtrl.custom"/> + <p class="help-block"> + Please separate multiple customs with space or comma + </p> + </div> + </td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + </fieldset> + </div> + </div> + <div class="modal-footer"> + <div ng-show="customModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert"> + <span class="pull-right"> {{customModalCtrl.error}}</span> + <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span> + </div> + <button class="btn btn-primary" ng-click="customModalCtrl.confirm()">Ok</button> + <button class="btn btn-default" ng-click="customModalCtrl.cancel()">Cancel</button> + </div> + </div>
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/installerModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/installerModal.html new file mode 100644 index 0000000..4be1375 --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/installerModal.html @@ -0,0 +1,59 @@ +<div class="ball" style="padding:5px;"> + <div class="modal-body"> + <div class="form-horizontal"> + <fieldset> + <div class="form-group"> + <legend>{{installerModalCtrl.data.text}}</legend> + <div class="row"> + <div class="update-project"> + <div class="col-sm-4"> + <label for="cpid" class="control-label col-sm-2"> Name: </label> + </div> + <div class="col-sm-6"> + <input type="text" class="form-control" ng-model="installerModalCtrl.installer.installer"/> + <p class="help-block"></p> + </div> + </div> + <div class="update-project"> + <div class="col-sm-4"> + <label for="cpid" class="control-label col-sm-2"> Version: </label> + </div> + <div class="col-sm-6"> + <button class="btn btn-primary" ng-click="installerModalCtrl.openVersionModal()">Add Version</button> + <p class="help-block"></p> + </div> + </div> + </div> + </div> + </fieldset> + </div> + <div class='clo-md-12' style="padding-right:0px"> + <h3>Version</h3> + <div class="table-responsive"> + <table class="table table-bordered table-hover" ng-data="installerModalCtrl.installer.versions"> + <thead> + <tr style=" + text-align: center;"> + <th style="width: 19%;">Version</th> + </tr> + </thead> + <tbody> + <tr ng-repeat-start="(index, version) in installerModalCtrl.installer.versions" style="padding:9px"> + <td>{{version.version}}</td> + </tr> + <tr ng-repeat-end=> + </tr> + </tbody> + </table> + </div> + </div> + </div> + <div class="modal-footer"> + <div ng-show="installerModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert"> + <span class="pull-right"> {{installerModalCtrl.error}}</span> + <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span> + </div> + <button class="btn btn-primary" ng-click="installerModalCtrl.confirm()">Ok</button> + <button class="btn btn-default" ng-click="installerModalCtrl.cancel()">Cancel</button> + </div> + </div>
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/projectModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/projectModal.html new file mode 100644 index 0000000..171cc33 --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/projectModal.html @@ -0,0 +1,59 @@ +<div class="ball" style="padding:5px;"> + <div class="modal-body"> + <div class="form-horizontal"> + <fieldset> + <div class="form-group"> + <legend>{{projectModalCtrl.data.text}}</legend> + <div class="row"> + <div class="update-project"> + <div class="col-sm-4"> + <label for="cpid" class="control-label"> Project Name: </label> + </div> + <div class="col-sm-6"> + <input type="text" class="form-control" ng-model="projectModalCtrl.project.project"/> + <p class="help-block"></p> + </div> + </div> + <div class="update-project"> + <div class="col-sm-4"> + <label for="cpid" class="control-label"> Custom: </label> + </div> + <div class="col-sm-6"> + <button class="btn btn-primary" ng-click="projectModalCtrl.openCustomModal()">Add Custom</button> + <p class="help-block"></p> + </div> + </div> + </div> + </div> + </fieldset> + </div> + <div class='clo-md-12' style="padding-right:0px"> + <h3>Customs</h3> + <div class="table-responsive"> + <table class="table table-bordered table-hover" ng-data="projectModalCtrl.project.customs"> + <thead> + <tr style=" + text-align: center;"> + <th style="width: 1%;">Custom</th> + </tr> + </thead> + <tbody> + <tr ng-repeat-start="custom in projectModalCtrl.project.customs" style="padding:9px"> + <td>{{custom}}</td> + </tr> + <tr ng-repeat-end=> + </tr> + </tbody> + </table> + </div> + </div> + </div> + <div class="modal-footer"> + <div ng-show="projectModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert"> + <span class="pull-right"> {{projectModalCtrl.error}}</span> + <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span> + </div> + <button class="btn btn-primary" ng-click="projectModalCtrl.confirm()">Ok</button> + <button class="btn btn-default" ng-click="projectModalCtrl.cancel()">Cancel</button> + </div> + </div>
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioModal.html new file mode 100644 index 0000000..2b5ba9e --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioModal.html @@ -0,0 +1,59 @@ +<div class="ball" style="padding:5px;"> + <div class="modal-body"> + <div class="form-horizontal"> + <fieldset> + <div class="form-group"> + <legend>{{scenarioModalController.data.text}}</legend> + <div class="row"> + <div class="update-project"> + <div class="col-sm-4"> + <label for="cpid" class="control-label col-sm-2"> Name: </label> + </div> + <div class="col-sm-6"> + <input type="text" class="form-control" ng-model="scenarioModalController.scenario.name"/> + <p class="help-block"></p> + </div> + </div> + <div class="update-project"> + <div class="col-sm-4"> + <label for="cpid" class="control-label col-sm-2"> Installer: </label> + </div> + <div class="col-sm-6"> + <button class="btn btn-primary" ng-click="scenarioModalController.openInstallerModal()">Add Installer</button> + <p class="help-block"></p> + </div> + </div> + </div> + </div> + </fieldset> + </div> + <div class='clo-md-12' style="padding-right:0px"> + <h3>Installers</h3> + <div class="table-responsive"> + <table class="table table-bordered table-hover" ng-data="scenarioModalController.scenario"> + <thead> + <tr style=" + text-align: center;"> + <th style="width: 19%;">Installers</th> + </tr> + </thead> + <tbody> + <tr ng-repeat-start="(index, installer) in scenarioModalController.scenario.installers" style="padding:9px"> + <td>{{installer.installer}}</td> + </tr> + <tr ng-repeat-end=> + </tr> + </tbody> + </table> + </div> + </div> + </div> + <div class="modal-footer"> + <div ng-show="scenarioModalController.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert"> + <span class="pull-right"> {{scenarioModalController.error}}</span> + <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span> + </div> + <button class="btn btn-primary" ng-click="scenarioModalController.confirm()">Ok</button> + <button class="btn btn-default" ng-click="scenarioModalController.cancel()">Cancel</button> + </div> +</div>
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioNameUpdate.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioNameUpdate.html new file mode 100644 index 0000000..e793c05 --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/scenarioNameUpdate.html @@ -0,0 +1,28 @@ +<div class="ball" style="padding:5px;"> + <div class="modal-body"> + <div class="form-horizontal"> + <fieldset> + <div class="form-group"> + <legend>{{ScenarioNameUpdateCtrl.data.text}}</legend> + <div class="row"> + <div class="update-project"> + <label for="cpid" class="control-label col-sm-4">Name: </label> + <div class="col-sm-6"> + <input type="text" class="form-control" ng-model="ScenarioNameUpdateCtrl.name"/> + <p class="help-block"></p> + </div> + </div> + </div> + </div> + </fieldset> + </div> + </div> + <div class="modal-footer"> + <div ng-show="ScenarioNameUpdateCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert"> + <span class="pull-right"> {{ScenarioNameUpdateCtrl.error}}</span> + <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span> + </div> + <button class="btn btn-primary" ng-click="ScenarioNameUpdateCtrl.confirm()">Ok</button> + <button class="btn btn-default" ng-click="ScenarioNameUpdateCtrl.cancel()">Cancel</button> + </div> + </div>
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/scoreModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/scoreModal.html new file mode 100644 index 0000000..55b5cfd --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/scoreModal.html @@ -0,0 +1,51 @@ + + + <div class="ball" style="padding:5px;"> + <div class="modal-body"> + <div class="form-horizontal"> + <fieldset> + <div class="form-group"> + <legend>{{scoreModalCtrl.data.text}}</legend> + <div class="row"> + <div class="update-project"> + <label for="cpid" class="control-label col-sm-4">Score: </label> + <div class="col-sm-6"> + <input type="text" class="form-control" ng-model="scoreModalCtrl.score.score"/> + <p class="help-block"></p> + </div> + </div> + <div class="update-project"> + <div> + <div class="col-md-4" style="text-align:right;"> + <span style="margin-top:6px;">Date: </span> + </div> + <div class="col-md-6"> + <p class="input-group" style="display:inline-flex;"> + <input type="text" class="form-control" + uib-datepicker-popup="{{scoreModalCtrl.format}}" + ng-model="scoreModalCtrl.score.date" is-open="scoreModalCtrl.endOpen" + close-text="Close" /> + <span class="input-group-btn"> + <button type="button" class="btn btn-default" ng-click="scoreModalCtrl.open($event, 'endOpen')"> + <i class="glyphicon glyphicon-calendar"></i> + </button> + </span> + </p> + </div> + </div> + </div> + </div> + </div> + </div> + </fieldset> + </div> + </div> + <div class="modal-footer"> + <div ng-show="scoreModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert"> + <span class="pull-right"> {{scoreModalCtrl.error}}</span> + <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span> + </div> + <button class="btn btn-primary" ng-click="scoreModalCtrl.confirm()">Ok</button> + <button class="btn btn-default" ng-click="scoreModalCtrl.cancel()">Cancel</button> + </div> + </div>
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/trustIndicatorModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/trustIndicatorModal.html new file mode 100644 index 0000000..b84bd5d --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/trustIndicatorModal.html @@ -0,0 +1,49 @@ +<div class="ball" style="padding:5px;"> + <div class="modal-body"> + <div class="form-horizontal"> + <fieldset> + <div class="form-group"> + <legend>{{trustIndicatorModalCtrl.data.text}}</legend> + <div class="row"> + <div class="update-project"> + <label for="cpid" class="control-label col-sm-4">Status: </label> + <div class="col-sm-6"> + <input type="text" class="form-control" ng-model="trustIndicatorModalCtrl.ti.status"/> + <p class="help-block"></p> + </div> + </div> + <div class="update-project"> + <div> + <div class="col-md-4" style="text-align:right;"> + <span style="margin-top:6px;">Date: </span> + </div> + <div class="col-md-6"> + <p class="input-group" style="display:inline-flex;"> + <input type="text" class="form-control" + uib-datepicker-popup="{{trustIndicatorModalCtrl.format}}" + ng-model="trustIndicatorModalCtrl.ti.date" is-open="trustIndicatorModalCtrl.endOpen" + close-text="Close" /> + <span class="input-group-btn"> + <button type="button" class="btn btn-default" ng-click="trustIndicatorModalCtrl.open($event, 'endOpen')"> + <i class="glyphicon glyphicon-calendar"></i> + </button> + </span> + </p> + </div> + </div> + </div> + </div> + </div> + </div> + </fieldset> + </div> + </div> + <div class="modal-footer"> + <div ng-show="trustIndicatorModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert"> + <span class="pull-right"> {{trustIndicatorModalCtrl.error}}</span> + <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span> + </div> + <button class="btn btn-primary" ng-click="trustIndicatorModalCtrl.confirm()">Ok</button> + <button class="btn btn-default" ng-click="trustIndicatorModalCtrl.cancel()">Cancel</button> + </div> + </div>
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/scenarios/modals/versionModal.html b/testapi/opnfv_testapi/ui/components/scenarios/modals/versionModal.html new file mode 100644 index 0000000..f679f0b --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/scenarios/modals/versionModal.html @@ -0,0 +1,68 @@ +<div class="ball" style="padding:5px;"> + <div class="modal-body"> + <div class="form-horizontal"> + <fieldset> + <div class="form-group"> + <legend>{{versionModalCtrl.data.text}}</legend> + <div class="row"> + <div class="update-project"> + <div class="col-sm-4"> + <label for="cpid" class="control-label col-sm-2"> Version: </label> + </div> + <div class="col-sm-6"> + <input type="text" class="form-control" ng-model="versionModalCtrl.version.version"/> + <p class="help-block"></p> + </div> + </div> + <div class="update-project"> + <div class="col-sm-4"> + <label for="cpid" class="control-label col-sm-2"> Owner: </label> + </div> + <div class="col-sm-6"> + <input type="text" class="form-control" ng-model="versionModalCtrl.version.owner"/> + <p class="help-block"></p> + </div> + </div> + <div class="update-project"> + <div class="col-sm-4"> + <label for="cpid" class="control-label col-sm-2"> Project: </label> + </div> + <div class="col-sm-4"> + <button class="btn btn-primary" ng-click="versionModalCtrl.openProjectModal()">Add Project:</button> + <p class="help-block"></p> + </div> + </div> + </div> + </div> + </fieldset> + </div> + <div class='clo-md-12' style="padding-right:0px"> + <h3>Projects</h3> + <div class="table-responsive"> + <table class="table table-bordered table-hover" ng-data="versionModalCtrl.version.projects"> + <thead> + <tr style=" + text-align: center;"> + <th style="width: 19%;">Project</th> + </tr> + </thead> + <tbody> + <tr ng-repeat-start="(index, project) in versionModalCtrl.version.projects" style="padding:9px"> + <td>{{project.project}}</td> + </tr> + <tr ng-repeat-end=> + </tr> + </tbody> + </table> + </div> + </div> + </div> + <div class="modal-footer"> + <div ng-show="versionModalCtrl.showCreateError" style="padding:0px;" class="col-md-6 alert alert-danger" role="alert"> + <span class="pull-right"> {{versionModalCtrl.error}}</span> + <span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true" >Error:</span> + </div> + <button class="btn btn-primary" ng-click="versionModalCtrl.confirm()">Ok</button> + <button class="btn btn-default" ng-click="versionModalCtrl.cancel()">Cancel</button> + </div> + </div>
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html new file mode 100644 index 0000000..d6d4257 --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenario.html @@ -0,0 +1,234 @@ +<legend>Scenario</legend> +<div style="padding-right:0px" class="col-md-12"> + <div class="table-responsive"> + <table class="table" ng-data="ctrl.data"> + <tbody> + <tr style="padding:9px"> + <td class="podsTableTd">Id :</td> + <td class="podsTableLeftTd">{{ctrl.data.scenarios[0]._id}}</td> + </tr> + <tr style="padding:9px"> + <td class="podsTableTd">Name :</td> + <td width="90%" class="podsTableLeftTd">{{ctrl.data.scenarios[0].name}}</td> + </tr> + <tr style="padding:9px"> + <td class="podsTableTd">Creator :</td> + <td width="90%" class="podsTableLeftTd">{{ctrl.data.scenarios[0].creator}}</td> + </tr> + <tr style="padding:9px"> + <td class="podsTableTd">Created at :</td> + <td width="90%" class="podsTableLeftTd">{{ctrl.data.scenarios[0].creation_date}}</td> + </tr> + <tr style="padding:9px"> + <td class="podsTableTd">Installers</td> + <td width="90%" class="podsTableLeftTd"> + <div class="col-md-1" style="padding:0px"> + <a ng-click="ctrl.expandInstallers()"> + <p ng-if="ctrl.collapeInstallers">Hide</p> + <p ng-if="!ctrl.collapeInstallers">Show</p> + </a> + </div> + <div class="col-md-1" style="padding:0px" ng-class="{'hidden' : !ctrl.buttonInstaller || (!auth.isAuthenticated && authenticate)}"> + <button type="button" class="btn btn-success btn-xs" ng-click="ctrl.openAddInstaller()" ><i class="fa fa-plus"></i>Add</button> + </div> + <div ng-class="{ 'hidden' : ! ctrl.collapeInstallers } "> + <div class="table-responsive"> + <table class="table " ng-data="ctrl.data.scenarios[0].installers"> + <tbody ng-repeat="(indexI, installer) in ctrl.data.scenarios[0].installers"> + <tr style="padding:9px"> + <td class="podsTableTd"> + {{indexI+1}}. Installer: + </td> + <td class="podsTableLeftTd" style="width:10%;padding-top: 7px;"> + <a ng-click="ctrl.expandInstaller(indexI)">{{installer.installer}}</a> + </td> + <td style="width:80%;border: none; padding: 0px;" ng-class="{'hidden' : !ctrl.buttonInstaller}"> + <button type="button" ng-class="{'hidden' : !auth.isAuthenticated && authenticate}" class="btn btn-danger btn-xs" ng-click="ctrl.openDeleteInstallerModal(installer.installer)" ><i class="fa fa-minus"></i>Delete</button> + </td> + </tr> + <tr ng-class="{ 'hidden' : ! ctrl.collapeInstaller[indexI] }"> + <td class="podsTableTd"> + Versions: + </td> + <td width="90%" class="podsTableLeftTd"> + <div class="col-md-1" style="padding:0px"> + <a ng-click="ctrl.expandVersions(indexI)"> + <p ng-if="ctrl.collapeVersions[indexI]">Hide</p> + <p ng-if="!ctrl.collapeVersions[indexI]">Show</p> + </a> + </div> + <div class="col-md-1" style="padding:0px" ng-class="{'hidden' : !ctrl.buttonVersion}"> + <button type="button" class="btn btn-success btn-xs" ng-class="{'hidden' : !auth.isAuthenticated && authenticate}" ng-click="ctrl.openAddVersionModal(installer.installer)" ><i class="fa fa-plus"></i>Add</button> + </div> + <div ng-class="{ 'hidden' : ! ctrl.collapeVersions[indexI] } " class="col-md-12"> + <div class="table-responsive"> + <table class="table " ng-data="inctrl.data.scenarios[0].installers"> + <tbody ng-repeat="(indexV, version) in installer.versions"> + <tr style="padding:9px"> + <td class="podsTableTd"> + {{indexV+1}}. Version: + </td> + <td class="podsTableLeftTd" style="width:10%;padding-top: 7px;"> + <a ng-click="ctrl.expandVersion(indexI,indexV)">{{version.version}}</a> + </td> + <td style="width:80%;border: none; padding: 0px;" ng-class="{'hidden' : !ctrl.buttonVersion}"> + <button type="button" class="btn btn-danger btn-xs" ng-class="{'hidden' : !auth.isAuthenticated && authenticate}" ng-click="ctrl.openDeleteVersionModal(version.version, installer.installer)" ><i class="fa fa-minus"></i>Delete</button> + </td> + </tr> + <tr style="padding:9px" ng-class="{ 'hidden' : ! ctrl.collapeVersion[indexI][indexV] } "> + <td class="podsTableTd"> + Owner: + </td> + <td class="podsTableLeftTd" style="width:90%">{{version.owner}}</td> + </tr> + <tr style="padding:9px" ng-class="{ 'hidden' : ! ctrl.collapeVersion[indexI][indexV] }"> + <td class="podsTableTd"> + Projects: + </td> + <td width="90%" class="podsTableLeftTd"> + <div class="col-md-1" style="padding:0px"> + <a ng-click="ctrl.expandProjects(indexI,indexV)"> + <p style="width:50%" ng-if="ctrl.collapeProjects[indexI][indexV]">Hide</p> + <p style="width:50%" ng-if="!ctrl.collapeProjects[indexI][indexV]">Show</p> + </a> + </div> + <div class="col-md-1" style="padding:0px" ng-class="{'hidden' : !ctrl.buttonProject }"> + <button type="button" ng-class="{'hidden' : !auth.isAuthenticated && authenticate}" class="btn btn-success btn-xs" ng-click="ctrl.openAddProjectModal(version.version,installer.installer)" ><i class="fa fa-plus"></i>Add</button> + </div> + <div ng-class="{ 'hidden' : ! ctrl.collapeProjects[indexI][indexV] } " class="col-md-12"> + <div class="table-responsive"> + <table class="table " ng-data="version.projects"> + <tbody ng-repeat="(indexP, project) in version.projects" > + <tr style="padding:9px"> + <td class="podsTableTd"> + {{indexP+1}}. Project: + </td> + <td class="podsTableLeftTd" style="width:10%;padding-top: 7px;"> + <a ng-click="ctrl.expandProject(indexI, indexV, indexP)">{{project.project}}</a> + </td> + <td style="width:80%;border: none; padding: 0px;" ng-class="{'hidden' : !ctrl.buttonProject}"> + <button type="button" class="btn btn-danger btn-xs" ng-class="{'hidden' : !auth.isAuthenticated && authenticate}" ng-click="ctrl.openDeleteProjectModal(project,version.version, installer.installer)" ><i class="fa fa-minus"></i>Delete</button> + </td> + </tr> + <tr ng-class="{ 'hidden' : ! ctrl.collapeProject[indexI][indexV][indexP] }"> + <td class="podsTableTd"> + Trust Indicators: + </td> + <td class="podsTableLeftTd" style="width:90%"> + <a ng-click="ctrl.expandTrustIndicator(indexI, indexV, indexP)"> + <p ng-if="ctrl.collapeTrustIndicator[indexI][indexV][indexP]">Hide</p> + <p ng-if="!ctrl.collapeTrustIndicator[indexI][indexV][indexP]">Show</p> + </a> + <table class="table " ng-class="{ 'hidden' : ! ctrl.collapeTrustIndicator[indexI][indexV][indexP] } " ng-data="project.trust_indicators"> + <tbody ng-repeat="(indexTI, trust_indicator) in project.trust_indicators" > + <tr style="padding:9px"> + <td class="podsTableTd"> + Status: + </td> + <td width="90%" class="podsTableLeftTd"> + {{trust_indicator.status}} + </td> + </tr> + <tr style="padding:9px"> + <td class="podsTableTd"> + Date: + </td> + <td width="90%" class="podsTableLeftTd"> + {{trust_indicator.date}} + </td> + </tr> + </tbody> + </table> + </td> + </tr> + <tr ng-class="{ 'hidden' : ! ctrl.collapeProject[indexI][indexV][indexP] }"> + <td class="podsTableTd"> + Scores: + </td> + <td class="podsTableLeftTd" style="width:90%"> + <a ng-click="ctrl.expandScore(indexI, indexV, indexP)"> + <p ng-if="ctrl.collapeScore[indexI][indexV][indexP]">Hide</p> + <p ng-if="!ctrl.collapeScore[indexI][indexV][indexP]">Show</p> + </a> + <table class="table" ng-class="{ 'hidden' : ! ctrl.collapeScore[indexI][indexV][indexP] } " ng-data="project.scores"> + <tbody ng-repeat="(indexSC, score) in project.scores" > + <tr style="padding:9px"> + <td class="podsTableTd"> + Score: + </td> + <td width="90%" class="podsTableLeftTd"> + {{score.score}} + </td> + </tr> + <tr style="padding:9px"> + <td class="podsTableTd"> + Date: + </td> + <td width="90%" class="podsTableLeftTd"> + {{score.date}} + </td> + </tr> + </tbody> + </table> + </td> + </tr> + <tr ng-class="{ 'hidden' : ! ctrl.collapeProject[indexI][indexV][indexP] }"> + <td class="podsTableTd"> + Customs: + </td> + <td class="podsTableLeftTd" style="width:90%"> + <a ng-click="ctrl.expandCustom(indexI, indexV, indexP)"> + <p ng-if="ctrl.collapeCustom[indexI][indexV][indexP]">Hide</p> + <p ng-if="!ctrl.collapeCustom[indexI][indexV][indexP]">Show</p> + </a> + <table class="table" ng-class="{ 'hidden' : ! ctrl.collapeCustom[indexI][indexV][indexP] } " ng-data="project.customs"> + <tbody> + <tr ng-repeat-start="(indexCU, custom) in project.customs" style="padding:9px"> + <td class="podsTableTd" style="float: none!important;"> + {{custom}} + </td> + <td width="90%" class="podsTableLeftTd"> + <button type="button" class="btn btn-danger btn-xs" ng-click="ctrl.openDeleteCustomModal(custom,project.project,version.version,installer.installer)" ng-class="{'hidden' : !auth.isAuthenticated && authenticate}" ><i class="fa fa-minus"></i>Delete</button> + </td> + </tr> + <tr ng-repeat-end=> + </tr> + <tr> + <button type="button" class="btn btn-success btn-xs" ng-click="ctrl.openAddCustomModal(project.project,version.version,installer.installer)" ng-class="{ 'hidden' : !ctrl.collapeCustom[indexI][indexV][indexP] || (!auth.isAuthenticated && authenticate)}"><i class="fa fa-plus"></i>Add</button> + </tr> + </tbody> + </table> + </td> + </tr> + <tr ng-repeat-end=> + </tr> + </tbody> + </table> + </div> + </div> + </td> + </tr> + </tbody> + </table> + </div> + </div> + </td> + </tr> + </tbody> + </table> + </div> + </div> + </td> + </tr> + </tbody> + </table> + </div> +</div> +<div class="row" style="margin-bottom:24px;"></div> +<div ng-class="{'show': ctrl.showError}" id="toast" class="error"> + <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true" ></span> + {{ctrl.error}}</div> +<div ng-class="{'show': ctrl.showSuccess}" id="toast" class="success"> + <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> + {{ctrl.success}}</div> +<div class="row" style="margin-bottom:24px;"></div>
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js new file mode 100644 index 0000000..e17718f --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/scenarios/scenario/scenarioController.js @@ -0,0 +1,605 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file 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. + */ + +(function () { + 'use strict'; + + angular + .module('testapiApp') + .controller('ScenarioController', ScenarioController); + + ScenarioController.$inject = [ + '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl','raiseAlert', + 'confirmModal', 'authenticate', '$timeout' + ]; + + /** + * TestAPI Scenario Controller + * This controller is for the '/Scenario/:name' page where a user can browse + * through Scenario declared in TestAPI. + */ + function ScenarioController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl, + raiseAlert, confirmModal, authenticate, $timeout) { + var ctrl = this; + ctrl.name = $state.params['name']; + ctrl.url = testapiApiUrl + '/scenarios?name=' + ctrl.name; + ctrl.expandInstallers = expandInstallers; + ctrl.expandInstaller = expandInstaller; + ctrl.expandInstaller = ctrl.expandInstaller; + ctrl.expandVersion = expandVersion; + ctrl.expandVersions = expandVersions; + ctrl.loadDetails = loadDetails; + ctrl.expandProjects = expandProjects + ctrl.expandProject = expandProject + ctrl.expandTrustIndicator = expandTrustIndicator; + ctrl.expandScore = expandScore; + ctrl.expandCustom = expandCustom; + ctrl.collapeVersion = []; + ctrl.collapeVersions = []; + ctrl.collapeProjects = []; + ctrl.collapeProject = []; + ctrl.collapeTrustIndicator = []; + ctrl.collapeScore = []; + ctrl.collapeCustom = []; + ctrl.collapeInstaller = []; + ctrl.addCustom = addCustom; + ctrl.openAddCustomModal = openAddCustomModal; + ctrl.openDeleteCustomModal = openDeleteCustomModal; + ctrl.deleteCustom = deleteCustom; + ctrl.addProject = addProject + ctrl.openAddProjectModal = openAddProjectModal + ctrl.openAddVersionModal = openAddVersionModal + ctrl.addVersion = addVersion + ctrl.openDeleteVersionModal = openDeleteVersionModal + ctrl.deleteVersion = deleteVersion + ctrl.openAddInstaller = openAddInstaller + ctrl.addInstaller = addInstaller + ctrl.openDeleteInstallerModal = openDeleteInstallerModal + ctrl.deleteInstaller = deleteInstaller + ctrl.openDeleteProjectModal = openDeleteProjectModal + ctrl.deleteProject = deleteProject + + ctrl.buttonInstaller = true + ctrl.buttonVersion = true + ctrl.buttonProject = true + ctrl.toastError = toastError + ctrl.toastSuccess = toastSuccess + + function toastError() { + ctrl.showError = true + $timeout(function(){ ctrl.showError = false;}, 3000); + } + + function toastSuccess() { + ctrl.showSuccess = true + $timeout(function(){ ctrl.showSuccess = false;}, 3000); + } + /** + * This will contact the TestAPI to get a listing of declared projects. + */ + function loadDetails() { + ctrl.showError = false; + ctrl.projectsRequest = + $http.get(ctrl.url).success(function (data) { + ctrl.data = data; + }).catch(function (error) { + ctrl.data = null; + ctrl.error = error.statusText + ctrl.toastError() + }); + } + + function expandTrustIndicator(indexI, indexV, indexP){ + if(ctrl.collapeTrustIndicator[indexI]==undefined){ + ctrl.collapeTrustIndicator[indexI] = [] + if(ctrl.collapeTrustIndicator[indexI][indexV]==undefined){ + ctrl.collapeTrustIndicator[indexI][indexV] = [] + } + } + if(ctrl.collapeTrustIndicator[indexI][indexV][indexP]){ + ctrl.collapeTrustIndicator[indexI][indexV][indexP] = false; + }else{ + ctrl.collapeTrustIndicator[indexI][indexV][indexP] = true; + } + } + + function expandScore(indexI, indexV, indexP){ + if(ctrl.collapeScore[indexI]==undefined){ + ctrl.collapeScore[indexI] = [] + if(ctrl.collapeScore[indexI][indexV]==undefined){ + ctrl.collapeScore[indexI][indexV] = [] + } + } + if(ctrl.collapeScore[indexI][indexV][indexP]){ + ctrl.collapeScore[indexI][indexV][indexP] = false; + }else{ + ctrl.collapeScore[indexI][indexV][indexP] = true; + } + } + + function expandCustom(indexI, indexV, indexP){ + if(ctrl.collapeCustom[indexI]==undefined){ + ctrl.collapeCustom[indexI] = [] + if(ctrl.collapeCustom[indexI][indexV]==undefined){ + ctrl.collapeCustom[indexI][indexV] = [] + } + } + if(ctrl.collapeCustom[indexI][indexV][indexP]){ + ctrl.collapeCustom[indexI][indexV][indexP] = false; + ctrl.buttonProject = true + }else{ + ctrl.collapeCustom[indexI][indexV][indexP] = true; + ctrl.buttonProject = false + } + } + + function expandVersion(indexI, indexV){ + if(ctrl.collapeVersion[indexI]==undefined){ + ctrl.collapeVersion[indexI] = [] + } + if(ctrl.collapeVersion[indexI][indexV]){ + ctrl.collapeVersion[indexI][indexV] = false; + }else{ + ctrl.collapeVersion[indexI][indexV] = true; + } + } + + function expandVersions(index){ + if(ctrl.collapeVersions[index]){ + ctrl.collapeVersions[index] = false; + ctrl.buttonInstaller = true + }else{ + ctrl.collapeVersions[index] = true; + ctrl.buttonInstaller = false + } + } + + function expandProjects(indexI, indexV){ + if(ctrl.collapeProjects[indexI]==undefined){ + ctrl.collapeProjects[indexI] = [] + } + if(ctrl.collapeProjects[indexI][indexV]){ + ctrl.collapeProjects[indexI][indexV] = false; + ctrl.buttonVersion = true + } + else{ + ctrl.collapeProjects[indexI][indexV]= true; + ctrl.buttonVersion = false + } + } + + function expandProject(indexI, indexV, indexP){ + if(ctrl.collapeProject[indexI]==undefined){ + ctrl.collapeProject[indexI] = [] + if(ctrl.collapeProject[indexI][indexV]==undefined){ + ctrl.collapeProject[indexI][indexV] = [] + } + } + if(ctrl.collapeProject[indexI][indexV][indexP]){ + ctrl.collapeProject[indexI][indexV][indexP] = false; + } + else{ + ctrl.collapeProject[indexI][indexV][indexP]= true; + } + } + + function expandInstaller(index){ + if(ctrl.collapeInstaller[index]){ + ctrl.collapeInstaller[index] = false; + } + else{ + ctrl.collapeInstaller[index]= true; + } + } + + function expandInstallers(){ + if(ctrl.collapeInstallers){ + ctrl.collapeInstallers= false + }else{ + ctrl.collapeInstallers= true + } + } + + function deleteInstaller(data){ + ctrl.installerReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/installers" + $http.delete(ctrl.installerReqest, {data: data.installers, headers: {'Content-Type': 'application/json'}}).success(function (data){ + ctrl.success = "Installer is successfully deleted." + ctrl.toastSuccess(); + ctrl.loadDetails(); + }) + .catch(function (data) { + ctrl.error = data.statusText; + ctrl.toastError() + }); + } + + function openDeleteInstallerModal(installer){ + var installers = [] + installers.push(installer) + var data = { + "installers": installers + } + confirmModal("Delete", 'installers', ctrl.deleteInstaller, data); + } + + function addInstaller(installer){ + var installers = [] + installers.push(installer) + ctrl.installerRequestUrl = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/installers" + ctrl.installerRequest = $http.post(ctrl.installerRequestUrl, installers) + ctrl.installerRequest.success(function (data){ + ctrl.success = "Installers are successfully updated." + ctrl.loadDetails(); + ctrl.toastSuccess(); + }) + .catch(function (data) { + ctrl.error = data.statusText; + ctrl.toastError(); + }); + return ctrl.installerRequest + } + + function openAddInstaller(){ + $uibModal.open({ + templateUrl: 'testapi-ui/components/scenarios/modals/installerModal.html', + controller: 'installerModalCtrl as installerModalCtrl', + size: 'md', + resolve: { + data: function () { + return { + text: "Add Installer", + successHandler: ctrl.addInstaller + }; + } + } + }); + } + + function addVersion(versions, installer){ + ctrl.versionRequestUrl = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/versions?installer="+installer + ctrl.versionRequest = $http.post(ctrl.versionRequestUrl, versions) + ctrl.versionRequest.success(function (data){ + ctrl.success = "Versions are successfully updated." + ctrl.loadDetails(); + ctrl.toastSuccess() + }) + .catch(function (data) { + ctrl.error = data.statusText; + ctrl.toastError() + }); + return ctrl.versionRequest; + } + + function openDeleteVersionModal(version, installer){ + var versions = [] + versions.push(version) + var data = { + "version": versions, + "installer": installer + } + confirmModal("Delete", "version", ctrl.deleteVersion, data); + } + + function deleteVersion(data){ + ctrl.versionReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/versions?installer="+data.installer + $http.delete(ctrl.versionReqest, {data: data.version, headers: {'Content-Type': 'application/json'}}).success(function (data){ + ctrl.success = "Versions are successfully deleted." + ctrl.loadDetails(); + ctrl.toastSuccess(); + }) + .catch(function (data) { + ctrl.error = data.statusText; + ctrl.toastError(); + }); + } + + function openAddVersionModal(installer){ + $uibModal.open({ + templateUrl: 'testapi-ui/components/scenarios/modals/versionModal.html', + controller: 'versionAddModalCtrl as versionModalCtrl', + size: 'md', + resolve: { + data: function () { + return { + text: "Add Version", + successHandler: ctrl.addVersion, + installer: installer + }; + } + } + }); + } + + function addProject(project, version, installer){ + ctrl.projectRequestUrl = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/projects?installer="+installer+"&version="+version + ctrl.projectRequest= $http.post(ctrl.projectRequestUrl, project) + ctrl.projectRequest.success(function (data){ + ctrl.success = "Projects are successfully updated." + ctrl.loadDetails(); + ctrl.toastSuccess(); + }) + .catch(function (data) { + ctrl.error = data.statusText; + ctrl.toastError(); + }); + return ctrl.projectRequest; + } + + function openAddProjectModal(version, installer){ + $uibModal.open({ + templateUrl: 'testapi-ui/components/scenarios/modals/projectModal.html', + controller: 'projectAddModalCtrl as projectModalCtrl', + size: 'md', + resolve: { + data: function () { + return { + text: "Add Project", + successHandler: ctrl.addProject, + version: version, + installer: installer + }; + } + } + }); + } + + function addCustom(custom,project,version,installer){ + ctrl.customRequestUrl = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/customs?installer="+installer+"&version="+version+"&project="+ project + ctrl.customRequest = $http.post(ctrl.customRequestUrl, custom) + ctrl.customRequest.success(function (data){ + ctrl.success = "Customs are successfully updated." + ctrl.loadDetails(); + ctrl.toastSuccess(); + }) + .catch(function (data) { + ctrl.error = data.statusText; + ctrl.toastError(); + }); + return ctrl.customRequest + } + + function openDeleteCustomModal(custom,project,version,installer){ + var customs = [] + customs.push(custom) + var data = { + "customs": customs, + "project": project, + "version": version, + "installer": installer + } + confirmModal("Delete", 'customs', ctrl.deleteCustom, data); + } + + function deleteCustom(data){ + ctrl.customReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/customs?installer="+data.installer+"&version="+data.version+"&project="+ data.project + $http.delete(ctrl.customReqest, {data: data.customs, headers: {'Content-Type': 'application/json'}}).success(function (data){ + ctrl.success = "Customs are successfully deleted." + ctrl.loadDetails(); + ctrl.toastSuccess(); + }) + .catch(function (data) { + ctrl.error = data.statusText; + ctrl.toastError(); + }); + } + + function openAddCustomModal(project,version,installer){ + $uibModal.open({ + templateUrl: 'testapi-ui/components/scenarios/modals/customModal.html', + controller: 'customAddModalCtrl as customModalCtrl', + size: 'md', + resolve: { + data: function () { + return { + text: "Add Custom", + successHandler: ctrl.addCustom, + project: project, + version: version, + installer: installer + }; + } + } + }); + } + + function openDeleteProjectModal(project, version, installer){ + var projects = [] + projects.push(project.project) + var data = { + "projects": projects, + "version": version, + "installer": installer + } + confirmModal("Delete", 'projects', ctrl.deleteProject, data); + } + + function deleteProject(data){ + ctrl.projectReqest = testapiApiUrl+ "/scenarios/"+ ctrl.name + "/projects?installer="+data.installer+"&version="+data.version + $http.delete(ctrl.projectReqest, {data: data.projects, headers: {'Content-Type': 'application/json'}}).success(function (data){ + ctrl.success = "Projects are successfully Deleted."; + ctrl.toastSuccess(); + ctrl.loadDetails(); + }) + .catch(function (data) { + ctrl.error = data.statusText; + ctrl.toastError(); + }); + } + + ctrl.loadDetails(); + } + + /** + * TestAPI Project Modal Controller + * This controller is for the create modal where a user can create + * the project information and for the edit modal where user can + * edit the project's details + */ + angular.module('testapiApp').controller('customAddModalCtrl', customAddModalCtrl); + customAddModalCtrl.$inject = ['$scope', '$uibModalInstance', 'data']; + function customAddModalCtrl($scope, $uibModalInstance, data) { + var ctrl = this; + ctrl.confirm = confirm; + ctrl.cancel = cancel; + ctrl.data = angular.copy(data); + + ctrl.customs = []; + + function confirm() { + var custom = ctrl.custom; + if(custom!="" && custom!=undefined ){ + ctrl.customs = custom.split(/[ ,]+/).filter(Boolean); + } + console.log(ctrl.customs) + ctrl.data.successHandler( + ctrl.customs, ctrl.data.project, + ctrl.data.version,ctrl.data.installer).success(function(){ + $uibModalInstance.dismiss('cancel'); + }); + + } + + /** + * Close the confirm modal without initiating changes. + */ + function cancel() { + $uibModalInstance.dismiss('cancel'); + } + } + + + /** + * TestAPI Project Modal Controller + * This controller is for the create modal where a user can create + * the project information and for the edit modal where user can + * edit the project's details + */ + angular.module('testapiApp').controller('projectAddModalCtrl', projectAddModalCtrl); + projectAddModalCtrl.$inject = ['$scope', '$uibModal', '$uibModalInstance', 'data']; + function projectAddModalCtrl($scope, $uibModal, $uibModalInstance, data) { + var ctrl = this; + ctrl.confirm = confirm; + ctrl.cancel = cancel; + ctrl.data = angular.copy(data); + ctrl.openCustomModal = openCustomModal; + ctrl.handleModalCustom = handleModalCustom; + ctrl.projects = [] + ctrl.project = { + "scores": [], + "trust_indicators": [], + "customs": [] + } + + + /** + * Initiate confirmation and call the success handler with the + * inputs. + */ + function confirm() { + ctrl.projects.push(ctrl.project) + ctrl.data.successHandler( + ctrl.projects, ctrl.data.version, ctrl.data.installer).success( function(){ + $uibModalInstance.dismiss('cancel'); + }); + + } + + /** + * Close the confirm modal without initiating changes. + */ + function cancel() { + $uibModalInstance.dismiss('cancel'); + } + + function handleModalCustom(custom){ + ctrl.project.customs.push(custom); + } + + function openCustomModal(){ + $uibModal.open({ + templateUrl: 'testapi-ui/components/scenarios/modals/customModal.html', + controller: 'customModalCtrl as customModalCtrl', + size: 'md', + resolve: { + data: function () { + return { + text: "Custom", + successHandler: ctrl.handleModalCustom + }; + } + } + }); + } + } + + /** + * TestAPI Project Modal Controller + * This controller is for the create modal where a user can create + * the project information and for the edit modal where user can + * edit the project's details + */ + angular.module('testapiApp').controller('versionAddModalCtrl', versionAddModalCtrl); + versionAddModalCtrl.$inject = ['$scope', '$uibModal','$uibModalInstance', 'data']; + function versionAddModalCtrl($scope, $uibModal, $uibModalInstance, data) { + var ctrl = this; + ctrl.confirm = confirm; + ctrl.cancel = cancel; + ctrl.data = angular.copy(data); + ctrl.openProjectModal = openProjectModal; + ctrl.handleModalData = handleModalData; + ctrl.versions = [] + ctrl.version = { + "projects": [] + } + + /** + * Initiate confirmation and call the success handler with the + * inputs. + */ + function confirm() { + ctrl.versions.push(ctrl.version) + ctrl.data.successHandler(ctrl.versions, ctrl.data.installer).success(function(){ + $uibModalInstance.dismiss('cancel'); + }); + + } + + /** + * Close the confirm modal without initiating changes. + */ + function cancel() { + $uibModalInstance.dismiss('cancel'); + } + + function handleModalData(project){ + ctrl.version.projects.push(project) + } + function openProjectModal(){ + $uibModal.open({ + templateUrl: 'testapi-ui/components/scenarios/modals/projectModal.html', + controller: 'projectModalCtrl as projectModalCtrl', + size: 'md', + resolve: { + data: function () { + return { + text: "Project", + successHandler: ctrl.handleModalData, + }; + } + } + }); + } + } + +})(); diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html b/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html new file mode 100644 index 0000000..8d23449 --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html @@ -0,0 +1,63 @@ +<h3>Scenarios</h3> +<div class="row" style="margin-bottom:24px;"></div> +<div class="row podsTable" style="vertical-align:middle"> + <div class="col-sm-1 pull-right" ng-class="{ 'hidden': !auth.isAuthenticated }" > + <button type="button" class="btn btn-danger" ng-click="ctrl.openBatchDeleteModal()"> + <i class="fa fa-minus"></i> Delete</button> + </div> + <div class="col-sm-2 pull-right" ng-class="{ 'hidden': !auth.isAuthenticated}"> + <button type="button" class="btn btn-success" ng-click="ctrl.openScenarioModal()"> + <i class="fa fa-plus"></i>Create</button> + </div> +</div> +<div ng-class="{'show': ctrl.showError}" id="toast" class="error"> + <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true" ></span> + {{ctrl.error}}</div> +<div ng-class="{'show': ctrl.showSuccess}" id="toast" class="success"> + <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> + {{ctrl.success}}</div> +<div class='clo-md-12' style="padding-right:0px"> + <div class="table-responsive"> + <table class="table table-bordered table-hover" ng-data="ctrl.data.scenarios"> + <thead> + <tr style=" + text-align: center;"> + <th style="width: 1%;">Bulk Select</th> + <th style="width: 80%;">Name + <a class="text-danger" ng-click="ctrl.sortBy()" ng-class="{ 'hidden': ctrl.sortName }" > + <span class="glyphicon glyphicon-sort-by-alphabet pull-right" aria-hidden="true"></span> + </a> + <a class="text-danger" ng-click="ctrl.sortBy()" ng-class="{ 'hidden': !ctrl.sortName}" > + <span class="glyphicon glyphicon-sort-by-alphabet-alt pull-right" aria-hidden="true"></span> + </a> + </th> + <th style="width: 19%;" ng-class="{'hidden': !auth.isAuthenticated}">Operations</th> + </tr> + </thead> + <tbody> + <tr ng-repeat-start="(index, scenario) in ctrl.data.scenarios" style="padding:9px"> + <td> + <div class="text-center"> + <input type="checkbox" value="{{scenario.name}}" ng-model="ctrl.checkBox[index]" > + </div> + </td> + <td> + <a class="text-info" ng-click="ctrl.viewScenario(scenario.name)"> + {{scenario.name}} + </a> + </td> + <td ng-class="{'hidden': !auth.isAuthenticated}"> + <span class="podsTable-col"> + <a class="text-warning" ng-click="ctrl.openUpdateModal(scenario.name)" title="Edit"> + <i class="fa fa-pencil-square-o"></i></a> + <a class="text-danger" ng-click="ctrl.openDeleteModal(scenario.name)" title="Delete"> + <i class="fa fa-trash-o"></i></a> + </span> + </td> + <tr ng-repeat-end=> + </tr> + </tbody> + </table> + </div> +</div> + diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js b/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js new file mode 100644 index 0000000..0aa5bf0 --- /dev/null +++ b/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js @@ -0,0 +1,513 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file 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. + */ + +(function () { + 'use strict'; + + angular + .module('testapiApp') + .controller('ScenariosController', ScenariosController); + + ScenariosController.$inject = [ + '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl', + 'raiseAlert', 'confirmModal', 'sortService', '$timeout' + ]; + + /** + * TestAPI Project Controller + * This controller is for the '/projects' page where a user can browse + * through projects declared in TestAPI. + */ + function ScenariosController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl, + raiseAlert, confirmModal, sortService, $timeout) { + var ctrl = this; + ctrl.url = testapiApiUrl + '/scenarios'; + + ctrl.createScenario = createScenario; + ctrl.listScenarios = listScenarios; + ctrl.openScenarioModal = openScenarioModal; + ctrl.viewScenario = viewScenario; + ctrl.openUpdateModal = openUpdateModal; + ctrl.updateScenarioName = updateScenarioName; + ctrl.openDeleteModal = openDeleteModal; + ctrl.deleteScenario = deleteScenario; + ctrl.openBatchDeleteModal = openBatchDeleteModal; + ctrl.deleteBatchScenario = deleteBatchScenario + ctrl.sortBy = sortBy + ctrl.checkBox = []; + ctrl.sortName = false + ctrl.toastError = toastError + ctrl.toastSuccess = toastSuccess + + function toastError() { + ctrl.showError = true + $timeout(function(){ ctrl.showError = false;}, 3000); + } + + function toastSuccess() { + ctrl.showSuccess = true + $timeout(function(){ ctrl.showSuccess = false;}, 3000); + } + + function openUpdateModal(name){ + $uibModal.open({ + templateUrl: 'testapi-ui/components/scenarios/modals/scenarioNameUpdate.html', + controller: 'ScenarioNameUpdateCtrl as ScenarioNameUpdateCtrl', + size: 'md', + resolve: { + data: function () { + return { + text: "Name Change: Scenario", + successHandler: ctrl.updateScenarioName, + name: name + }; + } + } + }); + } + + function openDeleteModal(name){ + confirmModal("Delete", 'scenarios', ctrl.deleteScenario,name); + } + + function sortBy(){ + ctrl.data.scenarios = sortService.sortFunction(ctrl.data.scenarios, 'name' , ctrl.sortName) + ctrl.sortName=!ctrl.sortName + } + + function deleteScenario(name){ + var scenarioURL = ctrl.url+"/"+name; + ctrl.scenarioRequest = + $http.delete(scenarioURL).success(function (data){ + ctrl.success = "Scenario is successfully deleted."; + ctrl.listScenarios(); + ctrl.toastSuccess(); + }).catch(function (data) { + ctrl.error = data.statusText; + ctrl.toastError() + }); + } + + function openBatchDeleteModal(){ + var deleteObjects = [] + ctrl.checkBox.forEach(function(scenario, index){ + if(!ctrl.showError){ + if(scenario){ + deleteObjects.push(ctrl.data.scenarios[index].name); + } + } + }); + confirmModal("Delete", 'scenarios', ctrl.deleteBatchScenario, deleteObjects); + } + + function deleteBatchScenario(){ + var index; + var checkedBox = []; + ctrl.checkBox.forEach(function(scenario, index){ + if(!ctrl.showError){ + if(scenario){ + deleteScenario(ctrl.data.scenarios[index].name); + } + } + }); + ctrl.checkBox = [] + } + + function updateScenarioName(newName, name){ + var scenarioURL = ctrl.url+"/"+name + var body = { + "name": newName + } + if(newName){ + ctrl.scenarioRequest = $http.put(scenarioURL, body) + ctrl.scenarioRequest.success(function (data){ + ctrl.success = "Scenario is successfully Updated." + ctrl.listScenarios(); + ctrl.toastSuccess(); + }).catch(function (data) { + ctrl.error = data.statusText; + ctrl.toastError(); + }); + return ctrl.scenarioRequest + }else{ + ctrl.error = "Name is missing"; + ctrl.toastError(); + } + } + + function viewScenario(name){ + $state.go('scenario', {'name':name}, {reload: true}); + } + + function createScenario(scenario) { + ctrl.scenarioRequest = $http.post(ctrl.url, scenario) + + ctrl.scenarioRequest.success(function (data){ + ctrl.success = "Scenario is successfully created."; + ctrl.toastSuccess(); + }).catch(function (data) { + ctrl.error = data.statusText; + ctrl.toastError(); + }); + + return ctrl.scenarioRequest; + } + + function listScenarios() { + ctrl.showError = false; + ctrl.resultsRequest = + $http.get(ctrl.url).success(function (data) { + ctrl.data = data; + ctrl.sortBy() + }).catch(function (data) { + ctrl.data = null; + ctrl.error = data.statusText; + ctrl.toastError(); + }); + } + + function openScenarioModal(){ + $uibModal.open({ + templateUrl: 'testapi-ui/components/scenarios/modals/scenarioModal.html', + controller: 'scenarioModalController as scenarioModalController', + size: 'md', + resolve: { + data: function () { + return { + text: "Scenario", + successHandler: ctrl.createScenario, + }; + } + } + }); + } + + listScenarios(); + } + + + /** + * TestAPI Project Modal Controller + * This controller is for the create modal where a user can create + * the project information and for the edit modal where user can + * edit the project's details + */ + angular.module('testapiApp').controller('scenarioModalController', scenarioModalController); + scenarioModalController.$inject = ['$scope', '$uibModal', '$uibModalInstance', 'data', '$q']; + function scenarioModalController($scope, $uibModal, $uibModalInstance, data, $q) { + var ctrl = this; + ctrl.confirm = confirm; + ctrl.cancel = cancel; + ctrl.data = angular.copy(data); + ctrl.handleModalData = handleModalData; + ctrl.openInstallerModal = openInstallerModal; + ctrl.scenario = { + "installers": [], + } + + + /** + * Initiate confirmation and call the success handler with the + * inputs. + */ + function confirm() { + ctrl.data.successHandler(ctrl.scenario).success(function(){ + $uibModalInstance.dismiss('cancel'); + }); + + } + + /** + * Close the confirm modal without initiating changes. + */ + function cancel() { + $uibModalInstance.dismiss('cancel'); + } + + function handleModalData(installer){ + ctrl.scenario.installers.push(installer) + var deferred = $q.defer(); + deferred.resolve(); + return deferred.promise; + } + + function openInstallerModal(){ + $uibModal.open({ + templateUrl: 'testapi-ui/components/scenarios/modals/installerModal.html', + controller: 'installerModalCtrl as installerModalCtrl', + size: 'md', + resolve: { + data: function () { + return { + text: "Installer", + successHandler: ctrl.handleModalData, + }; + } + } + }); + } + } + + /** + * TestAPI Project Modal Controller + * This controller is for the create modal where a user can create + * the project information and for the edit modal where user can + * edit the project's details + */ + angular.module('testapiApp').controller('installerModalCtrl', installerModalCtrl); + installerModalCtrl.$inject = ['$scope', '$uibModal', '$uibModalInstance', 'data']; + function installerModalCtrl($scope, $uibModal, $uibModalInstance, data) { + var ctrl = this; + ctrl.confirm = confirm; + ctrl.cancel = cancel; + ctrl.data = angular.copy(data); + ctrl.openVersionModal = openVersionModal; + ctrl.handleModalData = handleModalData; + ctrl.installer = { + "versions":[] + } + + + /** + * Initiate confirmation and call the success handler with the + * inputs. + */ + function confirm() { + ctrl.data.successHandler(ctrl.installer).success(function(){ + $uibModalInstance.dismiss('cancel'); + }); + + } + + /** + * Close the confirm modal without initiating changes. + */ + function cancel() { + $uibModalInstance.dismiss('cancel'); + } + + function handleModalData(version){ + ctrl.installer.versions.push(version); + } + + function openVersionModal(){ + $uibModal.open({ + templateUrl: 'testapi-ui/components/scenarios/modals/versionModal.html', + controller: 'versionModalCtrl as versionModalCtrl', + size: 'md', + resolve: { + data: function () { + return { + text: "Version", + successHandler: ctrl.handleModalData, + }; + } + } + }); + } + } + + /** + * TestAPI Project Modal Controller + * This controller is for the create modal where a user can create + * the project information and for the edit modal where user can + * edit the project's details + */ + angular.module('testapiApp').controller('versionModalCtrl', versionModalCtrl); + versionModalCtrl.$inject = ['$scope', '$uibModal','$uibModalInstance', 'data']; + function versionModalCtrl($scope, $uibModal, $uibModalInstance, data) { + var ctrl = this; + ctrl.confirm = confirm; + ctrl.cancel = cancel; + ctrl.data = angular.copy(data); + ctrl.openProjectModal = openProjectModal; + ctrl.handleModalData = handleModalData; + ctrl.version = { + "projects": [] + } + + /** + * Initiate confirmation and call the success handler with the + * inputs. + */ + function confirm() { + ctrl.data.successHandler(ctrl.version); + $uibModalInstance.dismiss('cancel'); + + } + + /** + * Close the confirm modal without initiating changes. + */ + function cancel() { + $uibModalInstance.dismiss('cancel'); + } + + function handleModalData(project){ + ctrl.version.projects.push(project) + } + function openProjectModal(){ + $uibModal.open({ + templateUrl: 'testapi-ui/components/scenarios/modals/projectModal.html', + controller: 'projectModalCtrl as projectModalCtrl', + size: 'md', + resolve: { + data: function () { + return { + text: "Project", + successHandler: ctrl.handleModalData, + }; + } + } + }); + } + } + + /** + * TestAPI Project Modal Controller + * This controller is for the create modal where a user can create + * the project information and for the edit modal where user can + * edit the project's details + */ + angular.module('testapiApp').controller('projectModalCtrl', projectModalCtrl); + projectModalCtrl.$inject = ['$scope', '$uibModal', '$uibModalInstance', 'data']; + function projectModalCtrl($scope, $uibModal, $uibModalInstance, data) { + var ctrl = this; + ctrl.confirm = confirm; + ctrl.cancel = cancel; + ctrl.data = angular.copy(data); + ctrl.openCustomModal = openCustomModal; + ctrl.handleModalCustom = handleModalCustom; + ctrl.project = { + "scores": [], + "trust_indicators": [], + "customs": [] + } + + + /** + * Initiate confirmation and call the success handler with the + * inputs. + */ + function confirm() { + + ctrl.data.successHandler(ctrl.project); + $uibModalInstance.dismiss('cancel'); + + } + + /** + * Close the confirm modal without initiating changes. + */ + function cancel() { + $uibModalInstance.dismiss('cancel'); + } + + function handleModalCustom(customs){ + for (var custom in customs){ + ctrl.project.customs.push(customs[custom]); + } + } + + function openCustomModal(){ + $uibModal.open({ + templateUrl: 'testapi-ui/components/scenarios/modals/customModal.html', + controller: 'customModalCtrl as customModalCtrl', + size: 'md', + resolve: { + data: function () { + return { + text: "Custom", + successHandler: ctrl.handleModalCustom + }; + } + } + }); + } + } + + /** + * TestAPI Project Modal Controller + * This controller is for the create modal where a user can create + * the project information and for the edit modal where user can + * edit the project's details + */ + angular.module('testapiApp').controller('customModalCtrl', customModalCtrl); + customModalCtrl.$inject = ['$scope', '$uibModalInstance', 'data']; + function customModalCtrl($scope, $uibModalInstance, data) { + var ctrl = this; + ctrl.confirm = confirm; + ctrl.cancel = cancel; + ctrl.data = angular.copy(data); + ctrl.open = open; + ctrl.customs = [] + + + /** + * Initiate confirmation and call the success handler with the + * inputs. + */ + function confirm() { + var custom = ctrl.custom; + if(custom!="" && custom!=undefined ){ + ctrl.customs = custom.split(/[ ,]+/).filter(Boolean); + } + ctrl.data.successHandler(ctrl.customs); + $uibModalInstance.dismiss('cancel'); + + } + + /** + * Close the confirm modal without initiating changes. + */ + function cancel() { + $uibModalInstance.dismiss('cancel'); + } + } + + /** + * TestAPI Project Modal Controller + * This controller is for the create modal where a user can create + * the project information and for the edit modal where user can + * edit the project's details + */ + angular.module('testapiApp').controller('ScenarioNameUpdateCtrl', ScenarioNameUpdateCtrl); + ScenarioNameUpdateCtrl.$inject = ['$scope', '$uibModalInstance', 'data']; + function ScenarioNameUpdateCtrl($scope, $uibModalInstance, data) { + var ctrl = this; + ctrl.confirm = confirm; + ctrl.cancel = cancel; + ctrl.data = angular.copy(data); + ctrl.open = open; + ctrl.name = ctrl.data.name; + + + /** + * Initiate confirmation and call the success handler with the + * inputs. + */ + function confirm() { + ctrl.data.successHandler(ctrl.name,ctrl.data.name).success( function() { + $uibModalInstance.dismiss('cancel'); + }) + } + + /** + * Close the confirm modal without initiating changes. + */ + function cancel() { + $uibModalInstance.dismiss('cancel'); + } + } +})(); diff --git a/testapi/opnfv_testapi/ui/config.json b/testapi/opnfv_testapi/ui/config.json index 26dfd08..63e1e97 100644 --- a/testapi/opnfv_testapi/ui/config.json +++ b/testapi/opnfv_testapi/ui/config.json @@ -1,2 +1,4 @@ -{"testapiApiUrl": "http://localhost:8000/api/v1", -"authenticate": true} +{ + "testapiApiUrl": "http://localhost:8000/api/v1", + "authenticate": true +}
\ No newline at end of file diff --git a/testapi/opnfv_testapi/ui/index.html b/testapi/opnfv_testapi/ui/index.html index 5e69e87..f345197 100644 --- a/testapi/opnfv_testapi/ui/index.html +++ b/testapi/opnfv_testapi/ui/index.html @@ -28,6 +28,7 @@ <link rel="stylesheet" href="testapi-ui/assets/lib/angular-busy/dist/angular-busy.min.css"> <link rel="stylesheet" href="testapi-ui/assets/css/style.css"> <link rel="stylesheet" href="testapi-ui/assets/lib/font-awesome-4.7.0/css/font-awesome.min.css"> + <link rel="stylesheet" href="testapi-ui/assets/lib/angular-json-tree/angular-json-tree.css" /> <script src="testapi-ui/assets/lib/jquery/jquery-3.2.1.min.js"></script> <script src="testapi-ui/assets/lib/bootstrap/dist/js/bootstrap.min.js"></script> @@ -36,6 +37,7 @@ <script src="testapi-ui/assets/lib/angular-resource/angular-resource.min.js"></script> <script src="testapi-ui/assets/lib/angular-bootstrap/ui-bootstrap-tpls.min.js"></script> <script src="testapi-ui/assets/lib/angular-busy/dist/angular-busy.min.js"></script> + <script src="testapi-ui/assets/lib/angular-json-tree/angular-json-tree.min.js"></script> <script src="testapi-ui/assets/lib/angular-confirm-modal/angular-confirm.js"></script> <script src="testapi-ui/app.js"></script> @@ -44,11 +46,15 @@ <script src="testapi-ui/shared/alerts/alertModalFactory.js"></script> <script src="testapi-ui/shared/alerts/confirmModalFactory.js"></script> <script src="testapi-ui/components/pods/podsController.js"></script> + <script src="testapi-ui/components/scenarios/scenario/scenarioController.js"></script> + <script src="testapi-ui/components/scenarios/scenariosController.js"></script> <script src="testapi-ui/components/pods/pod/podController.js"></script> <script src="testapi-ui/components/projects/projectsController.js"></script> <script src="testapi-ui/components/projects/project/projectController.js"></script> <script src="testapi-ui/components/results/resultsController.js"></script> <script src="testapi-ui/components/results/result/resultController.js"></script> + <script src="testapi-ui/components/deploy-results/deployResultsController.js"></script> + <script src="testapi-ui/components/deploy-results/deploy-result/deployResultController.js"></script> <script src="testapi-ui/components/profile/profileController.js"></script> <script src="testapi-ui/components/auth-failure/authFailureController.js"></script> <script src="testapi-ui/components/logout/logoutController.js"></script> diff --git a/testapi/opnfv_testapi/ui/package.json b/testapi/opnfv_testapi/ui/package.json index dc99239..2d4eb6e 100644 --- a/testapi/opnfv_testapi/ui/package.json +++ b/testapi/opnfv_testapi/ui/package.json @@ -3,6 +3,7 @@ "grunt": "~1.0.1", "grunt-contrib-connect": "^1.0.2", "grunt-contrib-copy": "^1.0.0", + "grunt-convert": "^0.1.12", "grunt-karma": "~2.0.0", "grunt-protractor-coverage": "^0.2.18", "grunt-protractor-runner": "~5.0.0", diff --git a/testapi/opnfv_testapi/tests/UI/protractor-conf.js b/testapi/opnfv_testapi/ui/protractor-conf.js index affbe5d..affbe5d 100644 --- a/testapi/opnfv_testapi/tests/UI/protractor-conf.js +++ b/testapi/opnfv_testapi/ui/protractor-conf.js diff --git a/testapi/opnfv_testapi/ui/shared/alerts/confirmModal.html b/testapi/opnfv_testapi/ui/shared/alerts/confirmModal.html index e5397e0..417af37 100644 --- a/testapi/opnfv_testapi/ui/shared/alerts/confirmModal.html +++ b/testapi/opnfv_testapi/ui/shared/alerts/confirmModal.html @@ -10,7 +10,7 @@ </div> <div class="Delete" ng-class="{ 'hidden': confirmModal.data.text!='Delete' }"> <div class="form-group"> - <label for="confirmText"> You are about to delete.</label> + <label for="confirmText"> You are about to delete following {{confirmModal.data.resource}} : {{confirmModal.deleteObjects}} </label> <br> Do you want to proceed? </div> diff --git a/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js b/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js index 5e79775..0286341 100644 --- a/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js +++ b/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js @@ -11,17 +11,19 @@ * Opens confirm modal dialog with input textbox */ function confirmModal($uibModal) { - return function(text, successHandler, name) { + return function(text, resource, successHandler, name) { $uibModal.open({ - templateUrl: '/testapi-ui/shared/alerts/confirmModal.html', + templateUrl: 'testapi-ui/shared/alerts/confirmModal.html', controller: 'CustomConfirmModalController as confirmModal', size: 'md', resolve: { data: function () { return { text: text, + resource: resource, successHandler: successHandler, name: name + }; } } @@ -44,8 +46,37 @@ ctrl.confirm = confirm; ctrl.cancel = cancel; - + ctrl.buildDeleteObjects = buildDeleteObjects; ctrl.data = angular.copy(data); + + function buildDeleteObjects(){ + ctrl.deleteObjects = ''; + if (typeof ctrl.data.name === 'string') { + ctrl.deleteObjects = ctrl.data.name + } + else if (ctrl.data.name instanceof Array){ + for(var index in ctrl.data.name){ + if(index==0){ + ctrl.deleteObjects += ctrl.data.name[index] + } + else{ + ctrl.deleteObjects += ", "+ ctrl.data.name[index] + } + + } + } + else{ + for(var index in ctrl.data.name[ctrl.data.resource]){ + if(index==0){ + ctrl.deleteObjects += ctrl.data.name[ctrl.data.resource][index] + } + else{ + ctrl.deleteObjects += ", "+ ctrl.data.name[ctrl.data.resource][index] + } + + } + } + } /** * Initiate confirmation and call the success handler with the * input text. @@ -63,5 +94,7 @@ function cancel() { $uibModalInstance.dismiss('cancel'); } + + ctrl.buildDeleteObjects(); } })(); diff --git a/testapi/opnfv_testapi/ui/shared/header/header.html b/testapi/opnfv_testapi/ui/shared/header/header.html index d0501a2..2b7be2f 100644 --- a/testapi/opnfv_testapi/ui/shared/header/header.html +++ b/testapi/opnfv_testapi/ui/shared/header/header.html @@ -19,9 +19,11 @@ TestAPI <li ng-class="{ active: header.isActive('/about')}"><a ui-sref="about">About</a></li> <li ng-class="{ active: header.isActive('/pods')}"><a ui-sref="pods">Pods</a></li> <li ng-class="{ active: header.isActive('/projects')}"><a ui-sref="projects">Projects</a></li> - <li ng-class="{ active: header.isActive('/results')}"><a ui-sref="results">Results</a></li> + <li ng-class="{ active: header.isActive('/results')}"><a ui-sref="results">Results</a></li> + <li ng-class="{ active: header.isActive('/deployresults')}"><a ui-sref="deployresults">Deploy Results</a></li> + <li ng-class="{ active: header.isActive('/scenarios')}"><a ui-sref="scenarios">Scenarios</a></li> </ul> - <ul class="nav navbar-nav navbar-right"> + <ul class="nav navbar-nav navbar-right" ng-class="{'hidden' : !authenticate}"> <li ng-class="{ active: header.isActive('/profile')}" ng-if="auth.isAuthenticated"><a ui-sref="profile">Profile</a></li> <li ng-if="auth.isAuthenticated"><a href="" ng-click="auth.doSignOut()">Sign Out</a></li> <li ng-if="!auth.isAuthenticated"><a href="" ng-click="auth.doSignIn()">Sign In / Sign Up</a></li> |