summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthuva4 <tharma.thuva@gmail.com>2017-11-14 15:38:56 +0530
committerthuva4 <tharma.thuva@gmail.com>2017-11-14 15:38:56 +0530
commit265e10a036b545d9d4e15bebef17e38e4b013af3 (patch)
tree253f52de1842ec2ca3dc5e33d381f6108c4c39ab
parent3b3477d3f632208d99fe2ab71679ab84b618855a (diff)
Create functionality and e2e tests for project
Implemented the create function for the projects. Wrote the e2e tests for the create function. Change-Id: Iceac650573ca31b6246350c4d60033b42e0ffb0f Signed-off-by: thuva4 <tharma.thuva@gmail.com>
-rw-r--r--testapi/3rd_party/static/testapi-ui/Gruntfile.js38
-rw-r--r--testapi/3rd_party/static/testapi-ui/app.js19
-rw-r--r--testapi/3rd_party/static/testapi-ui/index.html1
-rw-r--r--testapi/3rd_party/static/testapi-ui/shared/header/header.html1
-rw-r--r--testapi/opnfv_testapi/common/check.py8
-rw-r--r--testapi/opnfv_testapi/common/message.py4
-rw-r--r--testapi/opnfv_testapi/handlers/base_handlers.py2
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js23
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/projectControllerSpec.js224
-rw-r--r--testapi/opnfv_testapi/tests/unit/handlers/test_base.py8
-rw-r--r--testapi/opnfv_testapi/tests/unit/handlers/test_project.py30
-rw-r--r--testapi/opnfv_testapi/tests/unit/handlers/test_result.py6
-rw-r--r--testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py11
-rw-r--r--testapi/opnfv_testapi/ui/projects/projects.html38
-rw-r--r--testapi/opnfv_testapi/ui/projects/projectsController.js74
15 files changed, 444 insertions, 43 deletions
diff --git a/testapi/3rd_party/static/testapi-ui/Gruntfile.js b/testapi/3rd_party/static/testapi-ui/Gruntfile.js
index 8ff2802..f82269e 100644
--- a/testapi/3rd_party/static/testapi-ui/Gruntfile.js
+++ b/testapi/3rd_party/static/testapi-ui/Gruntfile.js
@@ -31,6 +31,12 @@ module.exports = function (grunt) {
},
components: {
expand: true,
+ cwd: '../../../opnfv_testapi/ui',
+ src: '**',
+ dest: 'components',
+ },
+ copyComponents: {
+ expand: true,
cwd: 'components',
src: '**',
dest: 'testapi-ui/components',
@@ -82,6 +88,12 @@ module.exports = function (grunt) {
async: true
}
},
+ deleteFiles: {
+ command: 'rm -r testapi-ui && rm -r components',
+ options: {
+ async: false
+ }
+ },
options: {
stdout: false,
stderr: false
@@ -90,8 +102,8 @@ module.exports = function (grunt) {
instrument: {
files: ['components/**/*.js'],
options: {
- lazy: false,
- basePath: "./testapi-ui/"
+ lazy: false,
+ basePath: "./testapi-ui/"
}
},
karma: {
@@ -105,7 +117,8 @@ module.exports = function (grunt) {
noColor: false,
coverageDir: '../../../opnfv_testapi/tests/UI/coverage',
args: {
- specs: ['../../../opnfv_testapi/tests/UI/e2e/podsControllerSpec.js']
+ specs: ['../../../opnfv_testapi/tests/UI/e2e/podsControllerSpec.js',
+ '../../../opnfv_testapi/tests/UI/e2e/projectControllerSpec.js']
}
},
local: {
@@ -119,18 +132,7 @@ module.exports = function (grunt) {
options: {
print: 'detail'
}
- },
- protractor: {
- e2e: {
- options: {
- args: {
- specs: ['../../../opnfv_testapi/tests/UI/e2e/podsControllerSpec.js']
- },
- configFile: '../../../opnfv_testapi/tests/UI/protractor-conf.js',
- keepAlive: true
- }
- }
- }
+ }
});
grunt.registerTask('test', [
'karma:unit'
@@ -138,6 +140,7 @@ module.exports = function (grunt) {
grunt.registerTask('e2e', [
'copy:assets',
'copy:components',
+ 'copy:copyComponents',
'copy:shared',
'copy:filesPng',
'copy:filesIco',
@@ -149,7 +152,8 @@ module.exports = function (grunt) {
'shell:startSelenium',
'wait:default',
'protractor_coverage',
- 'makeReport'
- // 'protractor'
+ 'makeReport',
+ 'shell:deleteFiles'
+
]);
}
diff --git a/testapi/3rd_party/static/testapi-ui/app.js b/testapi/3rd_party/static/testapi-ui/app.js
index 5f5b861..0b35162 100644
--- a/testapi/3rd_party/static/testapi-ui/app.js
+++ b/testapi/3rd_party/static/testapi-ui/app.js
@@ -64,6 +64,11 @@
templateUrl: 'testapi-ui/components/pods/pods.html',
controller: 'PodsController as ctrl'
}).
+ state('projects', {
+ url: '/projects',
+ templateUrl: 'testapi-ui/components/projects/projects.html',
+ controller: 'ProjectsController as ctrl'
+ }).
state('communityResults', {
url: '/community_results',
templateUrl: 'testapi-ui/components/results/results.html',
@@ -168,6 +173,7 @@
$rootScope.auth.doSignIn = doSignIn;
$rootScope.auth.doSignOut = doSignOut;
$rootScope.auth.doSignCheck = doSignCheck;
+ $rootScope.auth.doSubmitterCheck = doSubmitterCheck;
var sign_in_url = testapiApiUrl + '/auth/signin';
var sign_out_url = testapiApiUrl + '/auth/signout';
@@ -182,6 +188,7 @@
function doSignOut() {
$rootScope.auth.currentUser = null;
$rootScope.auth.isAuthenticated = false;
+ $rootScope.auth.projectNames = [];
$window.location.href = sign_out_url;
}
@@ -194,13 +201,25 @@
success(function (data) {
$rootScope.auth.currentUser = data;
$rootScope.auth.isAuthenticated = true;
+ $rootScope.auth.projectNames = $rootScope.auth.doSubmitterCheck(data.groups);
}).
error(function () {
$rootScope.auth.currentUser = null;
$rootScope.auth.isAuthenticated = false;
+ $rootScope.auth.projectNames = [];
});
}
+ function doSubmitterCheck(groups){
+ var projectNames = []
+ for(var index=0;index<groups.length; index++){
+ if(groups[index].indexOf('-submitters')>=0){
+ projectNames.push(groups[index].split('-')[2])
+ }
+ }
+ return projectNames;
+ }
+
$rootScope.auth.doSignCheck();
}
diff --git a/testapi/3rd_party/static/testapi-ui/index.html b/testapi/3rd_party/static/testapi-ui/index.html
index 2d7399f..45162dc 100644
--- a/testapi/3rd_party/static/testapi-ui/index.html
+++ b/testapi/3rd_party/static/testapi-ui/index.html
@@ -46,6 +46,7 @@
<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>
+ <script src="testapi-ui/components/projects/projectsController.js"></script>
<!-- Filters -->
<script src="testapi-ui/shared/filters.js"></script>
diff --git a/testapi/3rd_party/static/testapi-ui/shared/header/header.html b/testapi/3rd_party/static/testapi-ui/shared/header/header.html
index f5b2414..4b3f8dd 100644
--- a/testapi/3rd_party/static/testapi-ui/shared/header/header.html
+++ b/testapi/3rd_party/static/testapi-ui/shared/header/header.html
@@ -19,6 +19,7 @@ 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('/community_results')}"><a ui-sref="communityResults">Community Results</a></li>
+ <li ng-class="{ active: header.isActive('/projects')}"><a ui-sref="projects">Projects</a></li>
<!--
<li ng-class="{ active: header.isCatalogActive('public')}" class="dropdown" uib-dropdown>
<a role="button" class="dropdown-toggle" uib-dropdown-toggle>
diff --git a/testapi/opnfv_testapi/common/check.py b/testapi/opnfv_testapi/common/check.py
index 667578f..432a6c1 100644
--- a/testapi/opnfv_testapi/common/check.py
+++ b/testapi/opnfv_testapi/common/check.py
@@ -21,7 +21,7 @@ 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']:
+ if CONF.api_authenticate and self.table in ['pods', 'projects']:
testapi_id = self.get_secure_cookie(constants.TESTAPI_ID)
if not testapi_id:
raises.Unauthorized(message.not_login())
@@ -29,6 +29,12 @@ def is_authorized(method):
if not user_info:
raises.Unauthorized(message.not_lfid())
kwargs['owner'] = testapi_id
+ if self.table in ['projects']:
+ query = kwargs.get('query')
+ query_data = query()
+ group = "opnfv-gerrit-" + query_data['name'] + "-submitters"
+ if group not in user_info['groups']:
+ raises.Unauthorized(message.no_permission())
ret = yield gen.coroutine(method)(self, *args, **kwargs)
raise gen.Return(ret)
return wrapper
diff --git a/testapi/opnfv_testapi/common/message.py b/testapi/opnfv_testapi/common/message.py
index 3e14f72..b92b7f0 100644
--- a/testapi/opnfv_testapi/common/message.py
+++ b/testapi/opnfv_testapi/common/message.py
@@ -60,3 +60,7 @@ def no_update():
def must_int(name):
return '{} must be int'.format(name)
+
+
+def no_permission():
+ return 'You do not have permission to perform this action'
diff --git a/testapi/opnfv_testapi/handlers/base_handlers.py b/testapi/opnfv_testapi/handlers/base_handlers.py
index a8ee3db..df7f520 100644
--- a/testapi/opnfv_testapi/handlers/base_handlers.py
+++ b/testapi/opnfv_testapi/handlers/base_handlers.py
@@ -75,10 +75,10 @@ class GenericApiHandler(web.RequestHandler):
@web.asynchronous
@gen.coroutine
- @check.is_authorized
@check.valid_token
@check.no_body
@check.miss_fields
+ @check.is_authorized
@check.values_check
@check.carriers_exist
@check.new_not_exists
diff --git a/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js
index 66a57f2..8cf7467 100644
--- a/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js
+++ b/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js
@@ -12,7 +12,9 @@ describe('testing the Pods page for anonymous user', function () {
},
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"}]
+ pods: [{role: "community-ci", name: "test", owner: "testUser",
+ details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed",
+ creation_date: "2017-10-25 11:58:25.926168"}]
}
}
}]);
@@ -73,7 +75,8 @@ describe('testing the Pods page for anonymous user', function () {
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);
+ expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope'))
+ .isDisplayed()).toBe(true);
});
});
@@ -116,7 +119,9 @@ describe('testing the Pods page for authorized user', function () {
},
response: {
data: {
- "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", "user": "testUser", "groups": ["opnfv-testapi-users"], "email": "testuser@test.com"
+ "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed",
+ "user": "testUser", "groups": ["opnfv-testapi-users",
+ "opnfv-gerrit-functest-submitters"], "email": "testuser@test.com"
}
}
}
@@ -136,7 +141,8 @@ describe('testing the Pods page for authorized user', function () {
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);
+ expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope'))
+ .isDisplayed()).toBe(false);
});
});
@@ -170,7 +176,9 @@ describe('testing the Pods page for authorized user', function () {
},
response: {
data: {
- "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", "user": "testUser", "groups": ["opnfv-testapi-users"], "email": "testuser@test.com"
+ "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed",
+ "user": "testUser", "groups": ["opnfv-testapi-users"],
+ "email": "testuser@test.com"
}
}
}
@@ -182,7 +190,8 @@ describe('testing the Pods page for authorized user', function () {
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(true);
+ expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope'))
+ .isDisplayed()).toBe(true);
});
- })
+ });
}); \ 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
new file mode 100644
index 0000000..921625d
--- /dev/null
+++ b/testapi/opnfv_testapi/tests/UI/e2e/projectControllerSpec.js
@@ -0,0 +1,224 @@
+'use strict';
+
+var mock = require('protractor-http-mock');
+var baseURL = "http://localhost:8000"
+
+describe('testing the Project Link for anonymous user', function () {
+
+ it( 'should not show the Project Link for anonymous user', function() {
+ mock.teardown();
+ browser.get(baseURL);
+ var projectslink = element(by.linkText('Projects'));
+ expect(projectslink.isPresent()).toBe(true);
+ });
+
+ it( 'navigate anonymous user to project page', function() {
+ browser.get(baseURL+'#/projects');
+ var EC = browser.ExpectedConditions;
+ browser.wait(EC.urlContains(baseURL+ '/#/projects'), 10000);
+ });
+
+ it('create button is not visible for anonymous user ', function () {
+ browser.get(baseURL+'#/projects');
+ var buttonCreate = element(by.buttonText('Create'));
+ expect(buttonCreate.isDisplayed()).toBeFalsy();
+ });
+
+});
+
+describe('testing the Project Link for user who is not in submitter group', function () {
+ beforeEach(function(){
+ 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"
+ }
+ }
+ }
+ ]);
+ });
+
+ it( 'should show the Project Link for user', function() {
+ browser.get(baseURL);
+ var projectslink = element(by.linkText('Projects'));
+ expect(projectslink.isPresent()).toBe(true);
+ });
+
+ it( 'should navigate the user to the Project page', function() {
+ browser.get(baseURL);
+ var projectslink = element(by.linkText('Projects')).click();
+ var EC = browser.ExpectedConditions;
+ browser.wait(EC.urlContains(baseURL+ '/#/projects'), 10000);
+ });
+
+ it('create button is not visible for user', function () {
+ browser.get(baseURL+'#/projects');
+ var buttonCreate = element(by.buttonText('Create'));
+ expect(buttonCreate.isDisplayed()).toBeFalsy();
+ });
+})
+
+describe('testing the Project Link for user who is in submitter group', function () {
+ beforeEach(function(){
+ 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',
+ method: 'POST'
+ },
+ response: {
+ data: {
+ href: baseURL+"/api/v1/projects/testProject1"
+ }
+ }
+ },
+ {
+ request: {
+ path: '/api/v1/projects',
+ method: 'POST',
+ data: {
+ name: 'testProject2',
+ description : 'demoDescription',
+ }
+ },
+ response: {
+ status : 403
+ }
+ },
+ {
+ request: {
+ path: '/api/v1/projects',
+ method: 'POST',
+ data: {
+ name: 'testProject3',
+ description : 'demoDescription',
+ }
+ },
+ response: {
+ status : 403,
+ data : 'You do not have permission to perform this action'
+ }
+ }
+ ]);
+ });
+
+ it( 'should show the Project Link for user', function() {
+ browser.get(baseURL);
+ var projectslink = element(by.linkText('Projects'));
+ expect(projectslink.isPresent()).toBe(true);
+ });
+
+ it( 'should navigate the user to the Project page', function() {
+ browser.get(baseURL);
+ var projectslink = element(by.linkText('Projects')).click();
+ var EC = browser.ExpectedConditions;
+ browser.wait(EC.urlContains(baseURL+ '/#/projects'), 10000);
+ });
+
+ it('create button is visible for user', function () {
+ browser.get(baseURL+'#/projects');
+ var buttonCreate = element(by.buttonText('Create'));
+ 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."))
+ .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"))
+ .isDisplayed()).toBe(true);
+ });
+
+ 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'));
+ 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);
+ });
+
+ 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('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 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.ng-binding.ng-scope")).isDisplayed()).toBe(true);
+ });
+ });
+})
diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_base.py b/testapi/opnfv_testapi/tests/unit/handlers/test_base.py
index b7fabb9..eb147cc 100644
--- a/testapi/opnfv_testapi/tests/unit/handlers/test_base.py
+++ b/testapi/opnfv_testapi/tests/unit/handlers/test_base.py
@@ -16,6 +16,7 @@ from tornado import testing
from opnfv_testapi.models import base_models
from opnfv_testapi.models import pod_models
+from opnfv_testapi.models import project_models
from opnfv_testapi.tests.unit import fake_pymongo
@@ -43,6 +44,12 @@ class TestBase(testing.AsyncHTTPTestCase):
_id=str(ObjectId()),
owner='ValidUser',
create_date=str(datetime.now()))
+ self.project_e = project_models.Project(
+ name='functest',
+ description='functest test',
+ _id=str(ObjectId()),
+ create_date=str(datetime.now()))
+
self.req_d = None
self.req_e = None
self.addCleanup(self._clear)
@@ -53,6 +60,7 @@ class TestBase(testing.AsyncHTTPTestCase):
'groups': [
'opnfv-testapi-users',
'opnfv-gerrit-functest-submitters',
+ 'opnfv-gerrit-qtip-submitters',
'opnfv-gerrit-qtip-contributors']
})
diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_project.py b/testapi/opnfv_testapi/tests/unit/handlers/test_project.py
index 939cc0d..2873ab0 100644
--- a/testapi/opnfv_testapi/tests/unit/handlers/test_project.py
+++ b/testapi/opnfv_testapi/tests/unit/handlers/test_project.py
@@ -1,3 +1,11 @@
+##############################################################################
+# Copyright (c) 2016 ZTE Corporation
+# feng.xiaowei@zte.com.cn
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
import httplib
import unittest
@@ -10,10 +18,10 @@ from opnfv_testapi.tests.unit.handlers import test_base as base
class TestProjectBase(base.TestBase):
def setUp(self):
super(TestProjectBase, self).setUp()
- self.req_d = project_models.ProjectCreateRequest('vping',
- 'vping-ssh test')
- self.req_e = project_models.ProjectCreateRequest('doctor',
- 'doctor test')
+ self.req_d = project_models.ProjectCreateRequest('qtip',
+ 'qtip-ssh test')
+ self.req_e = project_models.ProjectCreateRequest('functest',
+ 'functest test')
self.get_res = project_models.Project
self.list_res = project_models.Projects
self.update_res = project_models.Project
@@ -29,22 +37,32 @@ class TestProjectBase(base.TestBase):
class TestProjectCreate(TestProjectBase):
+
+ @executor.create(httplib.BAD_REQUEST, message.not_login())
+ def test_notlogin(self):
+ return self.req_d
+
+ @executor.mock_valid_lfid()
@executor.create(httplib.BAD_REQUEST, message.no_body())
def test_withoutBody(self):
return None
+ @executor.mock_valid_lfid()
@executor.create(httplib.BAD_REQUEST, message.missing('name'))
def test_emptyName(self):
return project_models.ProjectCreateRequest('')
+ @executor.mock_valid_lfid()
@executor.create(httplib.BAD_REQUEST, message.missing('name'))
def test_noneName(self):
return project_models.ProjectCreateRequest(None)
+ @executor.mock_valid_lfid()
@executor.create(httplib.OK, 'assert_create_body')
def test_success(self):
return self.req_d
+ @executor.mock_valid_lfid()
@executor.create(httplib.FORBIDDEN, message.exist_base)
def test_alreadyExist(self):
self.create_d()
@@ -52,6 +70,8 @@ class TestProjectCreate(TestProjectBase):
class TestProjectGet(TestProjectBase):
+
+ @executor.mock_valid_lfid()
def setUp(self):
super(TestProjectGet, self).setUp()
self.create_d()
@@ -78,6 +98,7 @@ class TestProjectGet(TestProjectBase):
class TestProjectUpdate(TestProjectBase):
+ @executor.mock_valid_lfid()
def setUp(self):
super(TestProjectUpdate, self).setUp()
_, d_body = self.create_d()
@@ -115,6 +136,7 @@ class TestProjectUpdate(TestProjectBase):
class TestProjectDelete(TestProjectBase):
+ @executor.mock_valid_lfid()
def setUp(self):
super(TestProjectDelete, self).setUp()
self.create_d()
diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_result.py b/testapi/opnfv_testapi/tests/unit/handlers/test_result.py
index b9f9ede..bd482a6 100644
--- a/testapi/opnfv_testapi/tests/unit/handlers/test_result.py
+++ b/testapi/opnfv_testapi/tests/unit/handlers/test_result.py
@@ -15,7 +15,6 @@ import urllib
import unittest
from opnfv_testapi.common import message
-from opnfv_testapi.models import project_models
from opnfv_testapi.models import result_models
from opnfv_testapi.models import testcase_models
from opnfv_testapi.tests.unit import executor
@@ -86,15 +85,12 @@ class TestResultBase(base.TestBase):
self.list_res = result_models.TestResults
self.update_res = result_models.TestResult
self.basePath = '/api/v1/results'
- self.req_project = project_models.ProjectCreateRequest(
- self.project,
- 'vping test')
+ fake_pymongo.projects.insert(self.project_e.format())
self.req_testcase = testcase_models.TestcaseCreateRequest(
self.case,
'/cases/vping',
'vping-ssh test')
fake_pymongo.pods.insert(self.pod_d.format())
- self.create_help('/api/v1/projects', self.req_project)
self.create_help('/api/v1/projects/%s/cases',
self.req_testcase,
self.project)
diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py b/testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py
index e4c668e..d5e32e3 100644
--- a/testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py
+++ b/testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py
@@ -11,15 +11,16 @@ import httplib
import unittest
from opnfv_testapi.common import message
-from opnfv_testapi.models import project_models
from opnfv_testapi.models import testcase_models
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
class TestCaseBase(base.TestBase):
def setUp(self):
super(TestCaseBase, self).setUp()
+ self.project = 'functest'
self.req_d = testcase_models.TestcaseCreateRequest('vping_1',
'/cases/vping_1',
'vping-ssh test')
@@ -36,7 +37,7 @@ class TestCaseBase(base.TestBase):
self.list_res = testcase_models.Testcases
self.update_res = testcase_models.Testcase
self.basePath = '/api/v1/projects/%s/cases'
- self.create_project()
+ fake_pymongo.projects.insert(self.project_e.format())
def assert_body(self, case, req=None):
if not req:
@@ -56,12 +57,6 @@ class TestCaseBase(base.TestBase):
self.assertIsNotNone(new._id)
self.assertIsNotNone(new.creation_date)
- def create_project(self):
- req_p = project_models.ProjectCreateRequest('functest',
- 'vping-ssh test')
- self.create_help('/api/v1/projects', req_p)
- self.project = req_p.name
-
def create_d(self):
return super(TestCaseBase, self).create_d(self.project)
diff --git a/testapi/opnfv_testapi/ui/projects/projects.html b/testapi/opnfv_testapi/ui/projects/projects.html
new file mode 100644
index 0000000..62a968b
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/projects/projects.html
@@ -0,0 +1,38 @@
+<h3>Projects</h3>
+<p> </p>
+
+<div class="row" style="margin-bottom:24px;"></div>
+<div class="project-create" ng-class="{ 'hidden': ! (auth.projectNames.length>0) }">
+ <h4>Create</h4>
+ <div class="row">
+ <div ng-repeat="require in ctrl.createRequirements">
+ <div class="create-project" style="margin-left:24px;">
+ <p class="input-group">
+ <label for="cpid">{{require.label|capitalize}}: </label>
+ <a ng-if="require.type == 'text'">
+ <input type="text" dynamic-model="'ctrl.' + require.label"/>
+ </a>
+ <a ng-if="require.type == 'textarea'">
+ <textarea rows="2" cols="50" dynamic-model="'ctrl.' + require.label">
+ </textarea>
+ </a>
+ </p>
+ </div>
+ </div>
+
+ <div class="col-md-3" style="margin-top:12px; margin-left:8px;">
+ <button type="submit" class="btn btn-primary" ng-click="ctrl.create()">Create</button>
+ </div>
+ </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>
+
+<div ng-show="ctrl.showSuccess" class="alert alert-success" role="alert">
+ <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
+ Create Success
+</div> \ No newline at end of file
diff --git a/testapi/opnfv_testapi/ui/projects/projectsController.js b/testapi/opnfv_testapi/ui/projects/projectsController.js
new file mode 100644
index 0000000..d2640b6
--- /dev/null
+++ b/testapi/opnfv_testapi/ui/projects/projectsController.js
@@ -0,0 +1,74 @@
+/*
+ * 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('ProjectsController', ProjectsController);
+
+ ProjectsController.$inject = [
+ '$scope', '$http', '$filter', '$state', 'testapiApiUrl','raiseAlert'
+ ];
+
+ /**
+ * TestAPI Project Controller
+ * This controller is for the '/projects' page where a user can browse
+ * through projects declared in TestAPI.
+ */
+ function ProjectsController($scope, $http, $filter, $state, testapiApiUrl,
+ raiseAlert) {
+ var ctrl = this;
+ ctrl.url = testapiApiUrl + '/projects';
+ ctrl.create = create;
+
+ ctrl.createRequirements = [
+ {label: 'name', type: 'text', required: true},
+ {label: 'description', type: 'textarea', required: false}
+ ];
+
+ ctrl.name = '';
+ ctrl.details = '';
+
+ /**
+ * This will contact the TestAPI to create a new project.
+ */
+ function create() {
+ ctrl.showError = false;
+ ctrl.showSuccess = false;
+ if(ctrl.name != ""){
+ var projects_url = ctrl.url;
+ var body = {
+ name: ctrl.name,
+ description: ctrl.description
+ };
+ ctrl.projectsRequest =
+ $http.post(projects_url, body).success(function (data){
+ ctrl.showSuccess = true ;
+ })
+ .error(function (data) {
+ ctrl.showError = true;
+ ctrl.error = 'Error creating the new Project from server:' + angular.toJson(data);
+ });
+ ctrl.name = "";
+ ctrl.description="";
+ }
+ else{
+ ctrl.showError = true;
+ ctrl.error = 'Name is missing.'
+ }
+ }
+ }
+})();