Add tests to product page
This patch updates the product page to include tests associated to versions of the product. This allows filtering results based on a product_id. Tests associated with private products will have their product information hidden. Change-Id: Ic5b6b45c9e3d14d9c2cb36a8eba72f2a6e31d2aa
This commit is contained in:
parent
02307f3a1e
commit
5ad18f067f
@ -1,4 +1,5 @@
|
|||||||
<h3>Cloud Product</h3>
|
<h3>Cloud Product</h3>
|
||||||
|
<div cg-busy="{promise:ctrl.productRequest,message:'Loading'}"></div>
|
||||||
<div ng-show="ctrl.product" class="container-fluid">
|
<div ng-show="ctrl.product" class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="pull-left">
|
<div class="pull-left">
|
||||||
@ -14,6 +15,8 @@
|
|||||||
<div ng-include src="'components/products/partials/management.html'"></div>
|
<div ng-include src="'components/products/partials/management.html'"></div>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
<div ng-include src="'components/products/partials/versions.html'"></div>
|
<div ng-include src="'components/products/partials/versions.html'"></div>
|
||||||
|
<hr>
|
||||||
|
<div ng-include src="'components/products/partials/testsTable.html'"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
|
<div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<h3>Distro Product</h3>
|
<h3>Distro Product</h3>
|
||||||
|
<div cg-busy="{promise:ctrl.productRequest,message:'Loading'}"></div>
|
||||||
<div ng-show="ctrl.product" class="container-fluid">
|
<div ng-show="ctrl.product" class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="pull-left">
|
<div class="pull-left">
|
||||||
@ -14,6 +15,8 @@
|
|||||||
<div ng-include src="'components/products/partials/management.html'"></div>
|
<div ng-include src="'components/products/partials/management.html'"></div>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
<div ng-include src="'components/products/partials/versions.html'"></div>
|
<div ng-include src="'components/products/partials/versions.html'"></div>
|
||||||
|
<hr>
|
||||||
|
<div ng-include src="'components/products/partials/testsTable.html'"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
|
<div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
|
||||||
|
137
refstack-ui/app/components/products/partials/testsTable.html
Normal file
137
refstack-ui/app/components/products/partials/testsTable.html
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<h4><strong>Test Runs on Product</strong></h4>
|
||||||
|
<div cg-busy="{promise:ctrl.testsRequest,message:'Loading'}"></div>
|
||||||
|
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>Upload Date</th>
|
||||||
|
<th>Test Run ID</th>
|
||||||
|
<th>Product Version</th>
|
||||||
|
<th>Shared</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat-start="(index, result) in ctrl.testsData">
|
||||||
|
<td>
|
||||||
|
<a ng-if="!result.expanded"
|
||||||
|
class="glyphicon glyphicon-plus"
|
||||||
|
ng-click="result.expanded = true">
|
||||||
|
</a>
|
||||||
|
<a ng-if="result.expanded"
|
||||||
|
class="glyphicon glyphicon-minus"
|
||||||
|
ng-click="result.expanded = false">
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>{{result.created_at}}</td>
|
||||||
|
<td><a ui-sref="resultsDetail({testID: result.id})">{{result.id}}</a></td>
|
||||||
|
<td>{{result.product_version.version}}</td>
|
||||||
|
<td>
|
||||||
|
<span ng-show="result.meta.shared" class="glyphicon glyphicon-share"></span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr ng-if="result.expanded" ng-repeat-end>
|
||||||
|
<td></td>
|
||||||
|
<td colspan="4">
|
||||||
|
<strong>Publicly Shared:</strong>
|
||||||
|
<span ng-if="result.meta.shared == 'true' && !result.sharedEdit">Yes</span>
|
||||||
|
<span ng-if="!result.meta.shared && !result.sharedEdit">
|
||||||
|
<em>No</em>
|
||||||
|
</span>
|
||||||
|
<select ng-if="result.sharedEdit"
|
||||||
|
ng-model="result.meta.shared"
|
||||||
|
class="form-inline">
|
||||||
|
<option value="true">Yes</option>
|
||||||
|
<option value="">No</option>
|
||||||
|
</select>
|
||||||
|
<a ng-if="!result.sharedEdit"
|
||||||
|
ng-click="result.sharedEdit = true"
|
||||||
|
title="Edit"
|
||||||
|
class="glyphicon glyphicon-pencil"></a>
|
||||||
|
<a ng-if="result.sharedEdit"
|
||||||
|
ng-click="ctrl.associateTestMeta(index,'shared',result.meta.shared)"
|
||||||
|
title="Save"
|
||||||
|
class="glyphicon glyphicon-floppy-disk"></a>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<strong>Associated Guideline:</strong>
|
||||||
|
<span ng-if="!result.meta.guideline && !result.guidelineEdit">
|
||||||
|
<em>None</em>
|
||||||
|
</span>
|
||||||
|
<span ng-if="result.meta.guideline && !result.guidelineEdit">
|
||||||
|
{{result.meta.guideline.slice(0, -5)}}
|
||||||
|
</span>
|
||||||
|
<select ng-if="result.guidelineEdit"
|
||||||
|
ng-model="result.meta.guideline"
|
||||||
|
ng-options="o as o.slice(0, -5) for o in ctrl.versionList"
|
||||||
|
class="form-inline">
|
||||||
|
<option value="">None</option>
|
||||||
|
</select>
|
||||||
|
<a ng-if="!result.guidelineEdit"
|
||||||
|
ng-click="ctrl.getGuidelineVersionList();result.guidelineEdit = true"
|
||||||
|
title="Edit"
|
||||||
|
class="glyphicon glyphicon-pencil"></a>
|
||||||
|
<a ng-if="result.guidelineEdit"
|
||||||
|
ng-click="ctrl.associateTestMeta(index, 'guideline', result.meta.guideline)"
|
||||||
|
title="Save"
|
||||||
|
class="glyphicon glyphicon-floppy-disk">
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<strong>Associated Target Program:</strong>
|
||||||
|
<span ng-if="!result.meta.target && !result.targetEdit">
|
||||||
|
<em>None</em>
|
||||||
|
</span>
|
||||||
|
<span ng-if="result.meta.target && !result.targetEdit">
|
||||||
|
{{ctrl.targetMappings[result.meta.target]}}</span>
|
||||||
|
<select ng-if="result.targetEdit"
|
||||||
|
ng-model="result.meta.target"
|
||||||
|
class="form-inline">
|
||||||
|
<option value="">None</option>
|
||||||
|
<option value="platform">OpenStack Powered Platform</option>
|
||||||
|
<option value="compute">OpenStack Powered Compute</option>
|
||||||
|
<option value="object">OpenStack Powered Object Storage</option>
|
||||||
|
</select>
|
||||||
|
<a ng-if="!result.targetEdit"
|
||||||
|
ng-click="result.targetEdit = true"
|
||||||
|
title="Edit"
|
||||||
|
class="glyphicon glyphicon-pencil">
|
||||||
|
</a>
|
||||||
|
<a ng-if="result.targetEdit"
|
||||||
|
ng-click="ctrl.associateTestMeta(index, 'target', result.meta.target)"
|
||||||
|
title="Save"
|
||||||
|
class="glyphicon glyphicon-floppy-disk">
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<small>
|
||||||
|
<a ng-click="ctrl.unassociateTest(index)"
|
||||||
|
confirm="Are you sure you want to unassociate this test result with product: {{ctrl.product.name}}? Test result ownership will be given back to the original owner only.">
|
||||||
|
<span class="glyphicon glyphicon-remove-circle" ></span> Unassociate test result from product
|
||||||
|
</a>
|
||||||
|
</small>
|
||||||
|
</td>
|
||||||
|
</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.getProductTests()">
|
||||||
|
</uib-pagination>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-show="ctrl.showTestsError" class="alert alert-danger" role="alert">
|
||||||
|
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
|
||||||
|
<span class="sr-only">Error:</span>
|
||||||
|
{{ctrl.testsError}}
|
||||||
|
</div>
|
@ -37,8 +37,12 @@
|
|||||||
ctrl.getProductVersions = getProductVersions;
|
ctrl.getProductVersions = getProductVersions;
|
||||||
ctrl.deleteProduct = deleteProduct;
|
ctrl.deleteProduct = deleteProduct;
|
||||||
ctrl.deleteProductVersion = deleteProductVersion;
|
ctrl.deleteProductVersion = deleteProductVersion;
|
||||||
|
ctrl.getProductTests = getProductTests;
|
||||||
ctrl.switchProductPublicity = switchProductPublicity;
|
ctrl.switchProductPublicity = switchProductPublicity;
|
||||||
|
ctrl.associateTestMeta = associateTestMeta;
|
||||||
|
ctrl.getGuidelineVersionList = getGuidelineVersionList;
|
||||||
ctrl.addProductVersion = addProductVersion;
|
ctrl.addProductVersion = addProductVersion;
|
||||||
|
ctrl.unassociateTest = unassociateTest;
|
||||||
ctrl.openVersionModal = openVersionModal;
|
ctrl.openVersionModal = openVersionModal;
|
||||||
|
|
||||||
/** The product id extracted from the URL route. */
|
/** The product id extracted from the URL route. */
|
||||||
@ -49,8 +53,21 @@
|
|||||||
$state.go('home');
|
$state.go('home');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Mappings of DefCore components to marketing program names. */
|
||||||
|
ctrl.targetMappings = {
|
||||||
|
'platform': 'Openstack Powered Platform',
|
||||||
|
'compute': 'OpenStack Powered Compute',
|
||||||
|
'object': 'OpenStack Powered Object Storage'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pagination controls.
|
||||||
|
ctrl.currentPage = 1;
|
||||||
|
ctrl.itemsPerPage = 20;
|
||||||
|
ctrl.maxSize = 5;
|
||||||
|
|
||||||
ctrl.getProduct();
|
ctrl.getProduct();
|
||||||
ctrl.getProductVersions();
|
ctrl.getProductVersions();
|
||||||
|
ctrl.getProductTests();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will contact the Refstack API to get a product information.
|
* This will contact the Refstack API to get a product information.
|
||||||
@ -147,6 +164,30 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get tests runs associated with the current product.
|
||||||
|
*/
|
||||||
|
function getProductTests() {
|
||||||
|
ctrl.showTestsError = false;
|
||||||
|
var content_url = refstackApiUrl + '/results' +
|
||||||
|
'?page=' + ctrl.currentPage + '&product_id='
|
||||||
|
+ ctrl.id;
|
||||||
|
|
||||||
|
ctrl.testsRequest = $http.get(content_url).success(
|
||||||
|
function(data) {
|
||||||
|
ctrl.testsData = data.results;
|
||||||
|
ctrl.totalItems = data.pagination.total_pages *
|
||||||
|
ctrl.itemsPerPage;
|
||||||
|
ctrl.currentPage = data.pagination.current_page;
|
||||||
|
}
|
||||||
|
).error(function(error) {
|
||||||
|
ctrl.showTestsError = true;
|
||||||
|
ctrl.testsError =
|
||||||
|
'Error retrieving tests from server: ' +
|
||||||
|
angular.toJson(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will switch public/private property of the product.
|
* This will switch public/private property of the product.
|
||||||
*/
|
*/
|
||||||
@ -161,6 +202,73 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 associateTestMeta(index, key, value) {
|
||||||
|
var testId = ctrl.testsData[index].id;
|
||||||
|
var metaUrl = [
|
||||||
|
refstackApiUrl, '/results/', testId, '/meta/', key
|
||||||
|
].join('');
|
||||||
|
|
||||||
|
var editFlag = key + 'Edit';
|
||||||
|
if (value) {
|
||||||
|
ctrl.associateRequest = $http.post(metaUrl, value)
|
||||||
|
.success(function () {
|
||||||
|
ctrl.testsData[index][editFlag] = false;
|
||||||
|
}).error(function (error) {
|
||||||
|
raiseAlert('danger', error.title, error.detail);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctrl.unassociateRequest = $http.delete(metaUrl)
|
||||||
|
.success(function () {
|
||||||
|
ctrl.testsData[index][editFlag] = false;
|
||||||
|
}).error(function (error) {
|
||||||
|
raiseAlert('danger', error.title, error.detail);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve an array of available capability files from the Refstack
|
||||||
|
* 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 getGuidelineVersionList() {
|
||||||
|
if (ctrl.versionList) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var content_url = refstackApiUrl + '/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');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a PUT request to the API server to unassociate a product with
|
||||||
|
* a test result.
|
||||||
|
*/
|
||||||
|
function unassociateTest(index) {
|
||||||
|
var testId = ctrl.testsData[index].id;
|
||||||
|
var url = refstackApiUrl + '/results/' + testId;
|
||||||
|
ctrl.associateRequest = $http.put(url, {'product_version_id': null})
|
||||||
|
.success(function () {
|
||||||
|
ctrl.testsData.splice(index, 1);
|
||||||
|
}).error(function (error) {
|
||||||
|
raiseAlert('danger', error.title, error.detail);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will open the modal that will allow a product version
|
* This will open the modal that will allow a product version
|
||||||
* to be managed.
|
* to be managed.
|
||||||
|
@ -133,7 +133,8 @@
|
|||||||
*/
|
*/
|
||||||
function isEditingAllowed() {
|
function isEditingAllowed() {
|
||||||
return Boolean(ctrl.resultsData &&
|
return Boolean(ctrl.resultsData &&
|
||||||
ctrl.resultsData.user_role === 'owner');
|
(ctrl.resultsData.user_role === 'owner' ||
|
||||||
|
ctrl.resultsData.user_role == 'foundation'));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This tells you whether the current results are shared with the
|
* This tells you whether the current results are shared with the
|
||||||
|
@ -1107,6 +1107,9 @@ describe('Refstack controllers', function () {
|
|||||||
'cpid': null,
|
'cpid': null,
|
||||||
'version': '1.0',
|
'version': '1.0',
|
||||||
'product_id': '1234'}];
|
'product_id': '1234'}];
|
||||||
|
var fakeTestsResp = {'pagination': {'current_page': 1,
|
||||||
|
'total_pages': 1},
|
||||||
|
'results':[{'id': 'foo-test'}]};
|
||||||
var fakeVendorResp = {'id': 'fake-org-id',
|
var fakeVendorResp = {'id': 'fake-org-id',
|
||||||
'type': 3,
|
'type': 3,
|
||||||
'can_manage': true,
|
'can_manage': true,
|
||||||
@ -1134,6 +1137,8 @@ describe('Refstack controllers', function () {
|
|||||||
'/products/1234').respond(fakeProdResp);
|
'/products/1234').respond(fakeProdResp);
|
||||||
$httpBackend.when('GET', fakeApiUrl +
|
$httpBackend.when('GET', fakeApiUrl +
|
||||||
'/products/1234/versions').respond(fakeVersionResp);
|
'/products/1234/versions').respond(fakeVersionResp);
|
||||||
|
$httpBackend.when('GET', fakeApiUrl +
|
||||||
|
'/results?page=1&product_id=1234').respond(fakeTestsResp);
|
||||||
$httpBackend.when('GET', fakeApiUrl +
|
$httpBackend.when('GET', fakeApiUrl +
|
||||||
'/vendors/fake-org-id').respond(fakeVendorResp);
|
'/vendors/fake-org-id').respond(fakeVendorResp);
|
||||||
}));
|
}));
|
||||||
@ -1189,6 +1194,26 @@ describe('Refstack controllers', function () {
|
|||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should have a function to get tests on a product',
|
||||||
|
function () {
|
||||||
|
ctrl.getProductTests();
|
||||||
|
$httpBackend.flush();
|
||||||
|
expect(ctrl.testsData).toEqual(fakeTestsResp.results);
|
||||||
|
expect(ctrl.currentPage).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a function to unassociate a test from a product',
|
||||||
|
function () {
|
||||||
|
ctrl.testsData = [{'id': 'foo-test'}];
|
||||||
|
$httpBackend.expectPUT(
|
||||||
|
fakeApiUrl + '/results/foo-test',
|
||||||
|
{product_version_id: null})
|
||||||
|
.respond(200, {'id': 'foo-test'});
|
||||||
|
ctrl.unassociateTest(0);
|
||||||
|
$httpBackend.flush();
|
||||||
|
expect(ctrl.testsData).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
it('should have a function to switch the publicity of a project',
|
it('should have a function to switch the publicity of a project',
|
||||||
function () {
|
function () {
|
||||||
ctrl.product = {'public': true};
|
ctrl.product = {'public': true};
|
||||||
|
@ -21,6 +21,8 @@ CPID = 'cpid'
|
|||||||
PAGE = 'page'
|
PAGE = 'page'
|
||||||
SIGNED = 'signed'
|
SIGNED = 'signed'
|
||||||
VERIFICATION_STATUS = 'verification_status'
|
VERIFICATION_STATUS = 'verification_status'
|
||||||
|
PRODUCT_ID = 'product_id'
|
||||||
|
ALL_PRODUCT_TESTS = 'all_product_tests'
|
||||||
OPENID = 'openid'
|
OPENID = 'openid'
|
||||||
USER_PUBKEYS = 'pubkeys'
|
USER_PUBKEYS = 'pubkeys'
|
||||||
|
|
||||||
|
@ -51,7 +51,8 @@ class VersionsController(validation.BaseRestControllerWithValidation):
|
|||||||
if not product['public'] and not is_admin:
|
if not product['public'] and not is_admin:
|
||||||
pecan.abort(403, 'Forbidden.')
|
pecan.abort(403, 'Forbidden.')
|
||||||
|
|
||||||
return db.get_product_versions(id)
|
allowed_keys = ['id', 'product_id', 'version', 'cpid']
|
||||||
|
return db.get_product_versions(id, allowed_keys=allowed_keys)
|
||||||
|
|
||||||
@pecan.expose('json')
|
@pecan.expose('json')
|
||||||
def get_one(self, id, version_id):
|
def get_one(self, id, version_id):
|
||||||
@ -62,8 +63,8 @@ class VersionsController(validation.BaseRestControllerWithValidation):
|
|||||||
api_utils.check_user_is_vendor_admin(vendor_id))
|
api_utils.check_user_is_vendor_admin(vendor_id))
|
||||||
if not product['public'] and not is_admin:
|
if not product['public'] and not is_admin:
|
||||||
pecan.abort(403, 'Forbidden.')
|
pecan.abort(403, 'Forbidden.')
|
||||||
|
allowed_keys = ['id', 'product_id', 'version', 'cpid']
|
||||||
return db.get_product_version(version_id)
|
return db.get_product_version(version_id, allowed_keys=allowed_keys)
|
||||||
|
|
||||||
@secure(api_utils.is_authenticated)
|
@secure(api_utils.is_authenticated)
|
||||||
@pecan.expose('json')
|
@pecan.expose('json')
|
||||||
@ -171,19 +172,21 @@ class ProductsController(validation.BaseRestControllerWithValidation):
|
|||||||
@pecan.expose('json')
|
@pecan.expose('json')
|
||||||
def get_one(self, id):
|
def get_one(self, id):
|
||||||
"""Get information about product."""
|
"""Get information about product."""
|
||||||
product = db.get_product(id)
|
allowed_keys = ['id', 'name', 'description',
|
||||||
|
'product_ref_id', 'product_type',
|
||||||
|
'public', 'properties', 'created_at', 'updated_at',
|
||||||
|
'organization_id', 'created_by_user', 'type']
|
||||||
|
product = db.get_product(id, allowed_keys=allowed_keys)
|
||||||
vendor_id = product['organization_id']
|
vendor_id = product['organization_id']
|
||||||
is_admin = (api_utils.check_user_is_foundation_admin() or
|
is_admin = (api_utils.check_user_is_foundation_admin() or
|
||||||
api_utils.check_user_is_vendor_admin(vendor_id))
|
api_utils.check_user_is_vendor_admin(vendor_id))
|
||||||
if not is_admin and not product['public']:
|
if not is_admin and not product['public']:
|
||||||
pecan.abort(403, 'Forbidden.')
|
pecan.abort(403, 'Forbidden.')
|
||||||
|
|
||||||
if not is_admin:
|
if not is_admin:
|
||||||
allowed_keys = ['id', 'name', 'description', 'product_ref_id',
|
admin_only_keys = ['created_by_user', 'created_at', 'updated_at',
|
||||||
'type', 'product_type', 'public',
|
'properties']
|
||||||
'organization_id']
|
|
||||||
for key in product.keys():
|
for key in product.keys():
|
||||||
if key not in allowed_keys:
|
if key in admin_only_keys:
|
||||||
product.pop(key)
|
product.pop(key)
|
||||||
|
|
||||||
product['can_manage'] = is_admin
|
product['can_manage'] = is_admin
|
||||||
|
@ -112,7 +112,7 @@ class ResultsController(validation.BaseRestControllerWithValidation):
|
|||||||
test_info = db.get_test(
|
test_info = db.get_test(
|
||||||
test_id, allowed_keys=['id', 'cpid', 'created_at',
|
test_id, allowed_keys=['id', 'cpid', 'created_at',
|
||||||
'duration_seconds', 'meta',
|
'duration_seconds', 'meta',
|
||||||
'product_version_id',
|
'product_version',
|
||||||
'verification_status']
|
'verification_status']
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -123,6 +123,12 @@ class ResultsController(validation.BaseRestControllerWithValidation):
|
|||||||
'user_role': user_role})
|
'user_role': user_role})
|
||||||
|
|
||||||
if user_role not in (const.ROLE_FOUNDATION, const.ROLE_OWNER):
|
if user_role not in (const.ROLE_FOUNDATION, const.ROLE_OWNER):
|
||||||
|
# Don't expose product information if product is not public.
|
||||||
|
if (test_info.get('product_version') and
|
||||||
|
not test_info['product_version']['product_info']['public']):
|
||||||
|
|
||||||
|
test_info['product_version'] = None
|
||||||
|
|
||||||
test_info['meta'] = {
|
test_info['meta'] = {
|
||||||
k: v for k, v in six.iteritems(test_info['meta'])
|
k: v for k, v in six.iteritems(test_info['meta'])
|
||||||
if k in MetadataController.rw_access_keys
|
if k in MetadataController.rw_access_keys
|
||||||
@ -176,10 +182,22 @@ class ResultsController(validation.BaseRestControllerWithValidation):
|
|||||||
const.END_DATE,
|
const.END_DATE,
|
||||||
const.CPID,
|
const.CPID,
|
||||||
const.SIGNED,
|
const.SIGNED,
|
||||||
const.VERIFICATION_STATUS
|
const.VERIFICATION_STATUS,
|
||||||
|
const.PRODUCT_ID
|
||||||
]
|
]
|
||||||
|
|
||||||
filters = api_utils.parse_input_params(expected_input_params)
|
filters = api_utils.parse_input_params(expected_input_params)
|
||||||
|
|
||||||
|
if const.PRODUCT_ID in filters:
|
||||||
|
product = db.get_product(filters[const.PRODUCT_ID])
|
||||||
|
vendor_id = product['organization_id']
|
||||||
|
is_admin = (api_utils.check_user_is_foundation_admin() or
|
||||||
|
api_utils.check_user_is_vendor_admin(vendor_id))
|
||||||
|
if is_admin:
|
||||||
|
filters[const.ALL_PRODUCT_TESTS] = True
|
||||||
|
elif not product['public']:
|
||||||
|
pecan.abort(403, 'Forbidden.')
|
||||||
|
|
||||||
records_count = db.get_test_records_count(filters)
|
records_count = db.get_test_records_count(filters)
|
||||||
page_number, total_pages_number = \
|
page_number, total_pages_number = \
|
||||||
api_utils.get_page_number(records_count)
|
api_utils.get_page_number(records_count)
|
||||||
@ -187,13 +205,18 @@ class ResultsController(validation.BaseRestControllerWithValidation):
|
|||||||
try:
|
try:
|
||||||
per_page = CONF.api.results_per_page
|
per_page = CONF.api.results_per_page
|
||||||
results = db.get_test_records(page_number, per_page, filters)
|
results = db.get_test_records(page_number, per_page, filters)
|
||||||
|
is_foundation = api_utils.check_user_is_foundation_admin()
|
||||||
for result in results:
|
for result in results:
|
||||||
# Only show all metadata if the user is the owner or a member
|
|
||||||
# of the Foundation group.
|
|
||||||
if (not api_utils.check_owner(result['id']) and
|
|
||||||
not api_utils.check_user_is_foundation_admin()):
|
|
||||||
|
|
||||||
|
if not (api_utils.check_owner(result['id']) or is_foundation):
|
||||||
|
|
||||||
|
# Don't expose product info if the product is not public.
|
||||||
|
if (result.get('product_version') and not
|
||||||
|
result['product_version']['product_info']['public']):
|
||||||
|
|
||||||
|
result['product_version'] = None
|
||||||
|
# Only show all metadata if the user is the owner or a
|
||||||
|
# member of the Foundation group.
|
||||||
result['meta'] = {
|
result['meta'] = {
|
||||||
k: v for k, v in six.iteritems(result['meta'])
|
k: v for k, v in six.iteritems(result['meta'])
|
||||||
if k in MetadataController.rw_access_keys
|
if k in MetadataController.rw_access_keys
|
||||||
@ -209,8 +232,8 @@ class ResultsController(validation.BaseRestControllerWithValidation):
|
|||||||
}}
|
}}
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
LOG.debug('An error occurred during '
|
LOG.debug('An error occurred during '
|
||||||
'operation with database: %s' % ex)
|
'operation with database: %s' % str(ex))
|
||||||
pecan.abort(400)
|
pecan.abort(500)
|
||||||
|
|
||||||
return page
|
return page
|
||||||
|
|
||||||
@ -229,7 +252,8 @@ class ResultsController(validation.BaseRestControllerWithValidation):
|
|||||||
|
|
||||||
if kw['product_version_id']:
|
if kw['product_version_id']:
|
||||||
# Verify that the user is a member of the product's vendor.
|
# Verify that the user is a member of the product's vendor.
|
||||||
version = db.get_product_version(kw['product_version_id'])
|
version = db.get_product_version(kw['product_version_id'],
|
||||||
|
allowed_keys=['product_id'])
|
||||||
is_vendor_admin = (
|
is_vendor_admin = (
|
||||||
api_utils
|
api_utils
|
||||||
.check_user_is_product_admin(version['product_id'])
|
.check_user_is_product_admin(version['product_id'])
|
||||||
|
@ -210,9 +210,9 @@ def update_product(product_info):
|
|||||||
return IMPL.update_product(product_info)
|
return IMPL.update_product(product_info)
|
||||||
|
|
||||||
|
|
||||||
def get_product(id):
|
def get_product(id, allowed_keys=None):
|
||||||
"""Get product by id."""
|
"""Get product by id."""
|
||||||
return IMPL.get_product(id)
|
return IMPL.get_product(id, allowed_keys=allowed_keys)
|
||||||
|
|
||||||
|
|
||||||
def delete_product(id):
|
def delete_product(id):
|
||||||
|
@ -243,6 +243,13 @@ def _apply_filters_for_query(query, filters):
|
|||||||
query = query.filter(models.Test.verification_status ==
|
query = query.filter(models.Test.verification_status ==
|
||||||
verification_status)
|
verification_status)
|
||||||
|
|
||||||
|
if api_const.PRODUCT_ID in filters:
|
||||||
|
query = (query
|
||||||
|
.join(models.ProductVersion)
|
||||||
|
.filter(models.ProductVersion.product_id ==
|
||||||
|
filters[api_const.PRODUCT_ID]))
|
||||||
|
|
||||||
|
all_product_tests = filters.get(api_const.ALL_PRODUCT_TESTS)
|
||||||
signed = api_const.SIGNED in filters
|
signed = api_const.SIGNED in filters
|
||||||
# If we only want to get the user's test results.
|
# If we only want to get the user's test results.
|
||||||
if signed:
|
if signed:
|
||||||
@ -251,7 +258,9 @@ def _apply_filters_for_query(query, filters):
|
|||||||
.filter(models.TestMeta.meta_key == api_const.USER)
|
.filter(models.TestMeta.meta_key == api_const.USER)
|
||||||
.filter(models.TestMeta.value == filters[api_const.OPENID])
|
.filter(models.TestMeta.value == filters[api_const.OPENID])
|
||||||
)
|
)
|
||||||
else:
|
elif not all_product_tests:
|
||||||
|
# Get all non-signed (aka anonymously uploaded) test results
|
||||||
|
# along with signed but shared test results.
|
||||||
signed_results = (query.session
|
signed_results = (query.session
|
||||||
.query(models.TestMeta.test_id)
|
.query(models.TestMeta.test_id)
|
||||||
.filter_by(meta_key=api_const.USER))
|
.filter_by(meta_key=api_const.USER))
|
||||||
@ -260,6 +269,7 @@ def _apply_filters_for_query(query, filters):
|
|||||||
.filter_by(meta_key=api_const.SHARED_TEST_RUN))
|
.filter_by(meta_key=api_const.SHARED_TEST_RUN))
|
||||||
query = (query.filter(models.Test.id.notin_(signed_results))
|
query = (query.filter(models.Test.id.notin_(signed_results))
|
||||||
.union(query.filter(models.Test.id.in_(shared_results))))
|
.union(query.filter(models.Test.id.in_(shared_results))))
|
||||||
|
|
||||||
return query
|
return query
|
||||||
|
|
||||||
|
|
||||||
@ -505,13 +515,13 @@ def update_product(product_info):
|
|||||||
return _to_dict(product)
|
return _to_dict(product)
|
||||||
|
|
||||||
|
|
||||||
def get_product(id):
|
def get_product(id, allowed_keys=None):
|
||||||
"""Get product by id."""
|
"""Get product by id."""
|
||||||
session = get_session()
|
session = get_session()
|
||||||
product = session.query(models.Product).filter_by(id=id).first()
|
product = session.query(models.Product).filter_by(id=id).first()
|
||||||
if product is None:
|
if product is None:
|
||||||
raise NotFound('Product with id "%s" not found' % id)
|
raise NotFound('Product with id "%s" not found' % id)
|
||||||
return _to_dict(product)
|
return _to_dict(product, allowed_keys=allowed_keys)
|
||||||
|
|
||||||
|
|
||||||
def delete_product(id):
|
def delete_product(id):
|
||||||
@ -653,7 +663,8 @@ def get_product_versions(product_id, allowed_keys=None):
|
|||||||
"""Get all versions for a product."""
|
"""Get all versions for a product."""
|
||||||
session = get_session()
|
session = get_session()
|
||||||
version_info = (
|
version_info = (
|
||||||
session.query(models.ProductVersion).filter_by(product_id=product_id)
|
session.query(models.ProductVersion)
|
||||||
|
.filter_by(product_id=product_id).all()
|
||||||
)
|
)
|
||||||
return _to_dict(version_info, allowed_keys=allowed_keys)
|
return _to_dict(version_info, allowed_keys=allowed_keys)
|
||||||
|
|
||||||
|
@ -63,11 +63,12 @@ class Test(BASE, RefStackBase): # pragma: no cover
|
|||||||
sa.ForeignKey('product_version.id'),
|
sa.ForeignKey('product_version.id'),
|
||||||
nullable=True, unique=False)
|
nullable=True, unique=False)
|
||||||
verification_status = sa.Column(sa.Integer, nullable=False, default=0)
|
verification_status = sa.Column(sa.Integer, nullable=False, default=0)
|
||||||
|
product_version = orm.relationship('ProductVersion', backref='test')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _extra_keys(self):
|
def _extra_keys(self):
|
||||||
"""Relation should be pointed directly."""
|
"""Relation should be pointed directly."""
|
||||||
return ['results', 'meta']
|
return ['results', 'meta', 'product_version']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def metadata_keys(self):
|
def metadata_keys(self):
|
||||||
@ -79,7 +80,7 @@ class Test(BASE, RefStackBase): # pragma: no cover
|
|||||||
def default_allowed_keys(self):
|
def default_allowed_keys(self):
|
||||||
"""Default keys."""
|
"""Default keys."""
|
||||||
return ('id', 'created_at', 'duration_seconds', 'meta',
|
return ('id', 'created_at', 'duration_seconds', 'meta',
|
||||||
'product_version_id', 'verification_status')
|
'verification_status', 'product_version')
|
||||||
|
|
||||||
|
|
||||||
class TestResults(BASE, RefStackBase): # pragma: no cover
|
class TestResults(BASE, RefStackBase): # pragma: no cover
|
||||||
@ -245,9 +246,7 @@ class Product(BASE, RefStackBase): # pragma: no cover
|
|||||||
@property
|
@property
|
||||||
def default_allowed_keys(self):
|
def default_allowed_keys(self):
|
||||||
"""Default keys."""
|
"""Default keys."""
|
||||||
return ('id', 'name', 'description', 'product_ref_id', 'product_type',
|
return ('id', 'name', 'organization_id', 'public')
|
||||||
'public', 'properties', 'created_at', 'updated_at',
|
|
||||||
'organization_id', 'created_by_user', 'type')
|
|
||||||
|
|
||||||
|
|
||||||
class ProductVersion(BASE, RefStackBase):
|
class ProductVersion(BASE, RefStackBase):
|
||||||
@ -266,8 +265,14 @@ class ProductVersion(BASE, RefStackBase):
|
|||||||
cpid = sa.Column(sa.String(36), nullable=True)
|
cpid = sa.Column(sa.String(36), nullable=True)
|
||||||
created_by_user = sa.Column(sa.String(128), sa.ForeignKey('user.openid'),
|
created_by_user = sa.Column(sa.String(128), sa.ForeignKey('user.openid'),
|
||||||
nullable=False)
|
nullable=False)
|
||||||
|
product_info = orm.relationship('Product', backref='product_version')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _extra_keys(self):
|
||||||
|
"""Relation should be pointed directly."""
|
||||||
|
return ['product_info']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def default_allowed_keys(self):
|
def default_allowed_keys(self):
|
||||||
"""Default keys."""
|
"""Default keys."""
|
||||||
return ('id', 'product_id', 'version', 'cpid')
|
return ('id', 'version', 'cpid', 'product_info')
|
||||||
|
@ -135,6 +135,17 @@ class TestProductsEndpoint(api.FunctionalTest):
|
|||||||
self.get_json,
|
self.get_json,
|
||||||
self.URL + post_response.get('id'))
|
self.URL + post_response.get('id'))
|
||||||
|
|
||||||
|
mock_get_user.return_value = 'foo-open-id'
|
||||||
|
# Make product public.
|
||||||
|
product_info = {'id': post_response.get('id'), 'public': 1}
|
||||||
|
db.update_product(product_info)
|
||||||
|
|
||||||
|
# Test when getting product info when not owner/foundation.
|
||||||
|
get_response = self.get_json(self.URL + post_response.get('id'))
|
||||||
|
self.assertNotIn('created_by_user', get_response)
|
||||||
|
self.assertNotIn('created_at', get_response)
|
||||||
|
self.assertNotIn('updated_at', get_response)
|
||||||
|
|
||||||
@mock.patch('refstack.api.utils.get_user_id', return_value='test-open-id')
|
@mock.patch('refstack.api.utils.get_user_id', return_value='test-open-id')
|
||||||
def test_delete(self, mock_get_user):
|
def test_delete(self, mock_get_user):
|
||||||
"""Test delete request."""
|
"""Test delete request."""
|
||||||
@ -182,7 +193,7 @@ class TestProductsEndpoint(api.FunctionalTest):
|
|||||||
|
|
||||||
|
|
||||||
class TestProductVersionEndpoint(api.FunctionalTest):
|
class TestProductVersionEndpoint(api.FunctionalTest):
|
||||||
"""Test case for the 'product/<product_id>/version' API endpoint."""
|
"""Test case for the 'products/<product_id>/version' API endpoint."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestProductVersionEndpoint, self).setUp()
|
super(TestProductVersionEndpoint, self).setUp()
|
||||||
@ -218,7 +229,7 @@ class TestProductVersionEndpoint(api.FunctionalTest):
|
|||||||
|
|
||||||
response = self.get_json(self.URL)
|
response = self.get_json(self.URL)
|
||||||
self.assertEqual(2, len(response))
|
self.assertEqual(2, len(response))
|
||||||
self.assertEqual(post_response, response[1])
|
self.assertEqual(post_response['version'], response[1]['version'])
|
||||||
|
|
||||||
def test_get_one(self):
|
def test_get_one(self):
|
||||||
""""Test get a specific version."""
|
""""Test get a specific version."""
|
||||||
@ -228,7 +239,7 @@ class TestProductVersionEndpoint(api.FunctionalTest):
|
|||||||
version_id = post_response['id']
|
version_id = post_response['id']
|
||||||
|
|
||||||
response = self.get_json(self.URL + version_id)
|
response = self.get_json(self.URL + version_id)
|
||||||
self.assertEqual(post_response, response)
|
self.assertEqual(post_response['version'], response['version'])
|
||||||
|
|
||||||
# Test nonexistent version.
|
# Test nonexistent version.
|
||||||
self.assertRaises(webtest.app.AppError, self.get_json,
|
self.assertRaises(webtest.app.AppError, self.get_json,
|
||||||
@ -238,14 +249,17 @@ class TestProductVersionEndpoint(api.FunctionalTest):
|
|||||||
"""Test creating a product version."""
|
"""Test creating a product version."""
|
||||||
version = {'cpid': '123', 'version': '5.0'}
|
version = {'cpid': '123', 'version': '5.0'}
|
||||||
post_response = self.post_json(self.URL, params=json.dumps(version))
|
post_response = self.post_json(self.URL, params=json.dumps(version))
|
||||||
self.assertEqual(version['cpid'], post_response['cpid'])
|
|
||||||
self.assertEqual(version['version'], post_response['version'])
|
get_response = self.get_json(self.URL + post_response['id'])
|
||||||
self.assertEqual(self.product_id, post_response['product_id'])
|
self.assertEqual(version['cpid'], get_response['cpid'])
|
||||||
self.assertIn('id', post_response)
|
self.assertEqual(version['version'], get_response['version'])
|
||||||
|
self.assertEqual(self.product_id, get_response['product_id'])
|
||||||
|
self.assertIn('id', get_response)
|
||||||
|
|
||||||
# Test 'version' not in response body.
|
# Test 'version' not in response body.
|
||||||
self.assertRaises(webtest.app.AppError, self.get_json,
|
response = self.post_json(self.URL, expect_errors=True,
|
||||||
self.URL + '/sdsdsds')
|
params=json.dumps({'cpid': '123'}))
|
||||||
|
self.assertEqual(400, response.status_code)
|
||||||
|
|
||||||
def test_put(self):
|
def test_put(self):
|
||||||
"""Test updating a product version."""
|
"""Test updating a product version."""
|
||||||
|
@ -119,13 +119,13 @@ class TestResultsEndpoint(api.FunctionalTest):
|
|||||||
self.put_json(url, params=json.dumps(body))
|
self.put_json(url, params=json.dumps(body))
|
||||||
get_response = self.get_json(url)
|
get_response = self.get_json(url)
|
||||||
self.assertEqual(version_response['id'],
|
self.assertEqual(version_response['id'],
|
||||||
get_response['product_version_id'])
|
get_response['product_version']['id'])
|
||||||
|
|
||||||
# Test when product_version_id is None.
|
# Test when product_version_id is None.
|
||||||
body = {'product_version_id': None}
|
body = {'product_version_id': None}
|
||||||
self.put_json(url, params=json.dumps(body))
|
self.put_json(url, params=json.dumps(body))
|
||||||
get_response = self.get_json(url)
|
get_response = self.get_json(url)
|
||||||
self.assertIsNone(get_response['product_version_id'])
|
self.assertIsNone(get_response['product_version'])
|
||||||
|
|
||||||
# Test when test verification preconditions are not met.
|
# Test when test verification preconditions are not met.
|
||||||
body = {'verification_status': api_const.TEST_VERIFIED}
|
body = {'verification_status': api_const.TEST_VERIFIED}
|
||||||
@ -167,7 +167,7 @@ class TestResultsEndpoint(api.FunctionalTest):
|
|||||||
self.put_json(url, params=json.dumps(body))
|
self.put_json(url, params=json.dumps(body))
|
||||||
get_response = self.get_json(url)
|
get_response = self.get_json(url)
|
||||||
self.assertEqual(version_response['id'],
|
self.assertEqual(version_response['id'],
|
||||||
get_response['product_version_id'])
|
get_response['product_version']['id'])
|
||||||
|
|
||||||
# Test non-Foundation user can't change verification_status.
|
# Test non-Foundation user can't change verification_status.
|
||||||
body = {'verification_status': 1}
|
body = {'verification_status': 1}
|
||||||
@ -328,6 +328,67 @@ class TestResultsEndpoint(api.FunctionalTest):
|
|||||||
filtering_results = self.get_json(url)
|
filtering_results = self.get_json(url)
|
||||||
self.assertEqual([], filtering_results['results'])
|
self.assertEqual([], filtering_results['results'])
|
||||||
|
|
||||||
|
@mock.patch('refstack.api.utils.get_user_id')
|
||||||
|
def test_get_with_product_id(self, mock_get_user):
|
||||||
|
user_info = {
|
||||||
|
'openid': 'test-open-id',
|
||||||
|
'email': 'foo@bar.com',
|
||||||
|
'fullname': 'Foo Bar'
|
||||||
|
}
|
||||||
|
db.user_save(user_info)
|
||||||
|
|
||||||
|
mock_get_user.return_value = 'test-open-id'
|
||||||
|
|
||||||
|
fake_product = {
|
||||||
|
'name': 'product name',
|
||||||
|
'description': 'product description',
|
||||||
|
'product_type': api_const.CLOUD,
|
||||||
|
}
|
||||||
|
|
||||||
|
product = json.dumps(fake_product)
|
||||||
|
response = self.post_json('/v1/products/', params=product)
|
||||||
|
product_id = response['id']
|
||||||
|
|
||||||
|
# Create a version.
|
||||||
|
version_url = '/v1/products/' + product_id + '/versions'
|
||||||
|
version = {'cpid': '123', 'version': '6.0'}
|
||||||
|
post_response = self.post_json(version_url, params=json.dumps(version))
|
||||||
|
version_id = post_response['id']
|
||||||
|
|
||||||
|
# Create a test and associate it to the product version and user.
|
||||||
|
results = json.dumps(FAKE_TESTS_RESULT)
|
||||||
|
post_response = self.post_json('/v1/results', params=results)
|
||||||
|
test_id = post_response['test_id']
|
||||||
|
test_info = {'id': test_id, 'product_version_id': version_id}
|
||||||
|
db.update_test(test_info)
|
||||||
|
db.save_test_meta_item(test_id, api_const.USER, 'test-open-id')
|
||||||
|
|
||||||
|
url = self.URL + '?page=1&product_id=' + product_id
|
||||||
|
|
||||||
|
# Test GET.
|
||||||
|
response = self.get_json(url)
|
||||||
|
self.assertEqual(1, len(response['results']))
|
||||||
|
self.assertEqual(test_id, response['results'][0]['id'])
|
||||||
|
|
||||||
|
# Test unauthorized.
|
||||||
|
mock_get_user.return_value = 'test-foo-id'
|
||||||
|
response = self.get_json(url, expect_errors=True)
|
||||||
|
self.assertEqual(403, response.status_code)
|
||||||
|
|
||||||
|
# Make product public.
|
||||||
|
product_info = {'id': product_id, 'public': 1}
|
||||||
|
db.update_product(product_info)
|
||||||
|
|
||||||
|
# Test result is not shared yet, so no tests should return.
|
||||||
|
response = self.get_json(url)
|
||||||
|
self.assertFalse(response['results'])
|
||||||
|
|
||||||
|
# Share the test run.
|
||||||
|
db.save_test_meta_item(test_id, api_const.SHARED_TEST_RUN, 1)
|
||||||
|
response = self.get_json(url)
|
||||||
|
self.assertEqual(1, len(response['results']))
|
||||||
|
self.assertEqual(test_id, response['results'][0]['id'])
|
||||||
|
|
||||||
@mock.patch('refstack.api.utils.check_owner')
|
@mock.patch('refstack.api.utils.check_owner')
|
||||||
def test_delete(self, mock_check_owner):
|
def test_delete(self, mock_check_owner):
|
||||||
results = json.dumps(FAKE_TESTS_RESULT)
|
results = json.dumps(FAKE_TESTS_RESULT)
|
||||||
|
@ -141,7 +141,7 @@ class ResultsControllerTestCase(BaseControllerTestCase):
|
|||||||
mock_get_test.assert_called_once_with(
|
mock_get_test.assert_called_once_with(
|
||||||
'fake_arg', allowed_keys=['id', 'cpid', 'created_at',
|
'fake_arg', allowed_keys=['id', 'cpid', 'created_at',
|
||||||
'duration_seconds', 'meta',
|
'duration_seconds', 'meta',
|
||||||
'product_version_id',
|
'product_version',
|
||||||
'verification_status']
|
'verification_status']
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -251,6 +251,7 @@ class ResultsControllerTestCase(BaseControllerTestCase):
|
|||||||
const.CPID,
|
const.CPID,
|
||||||
const.SIGNED,
|
const.SIGNED,
|
||||||
const.VERIFICATION_STATUS,
|
const.VERIFICATION_STATUS,
|
||||||
|
const.PRODUCT_ID
|
||||||
]
|
]
|
||||||
page_number = 1
|
page_number = 1
|
||||||
total_pages_number = 10
|
total_pages_number = 10
|
||||||
|
@ -769,7 +769,7 @@ class DBBackendTestCase(base.BaseTestCase):
|
|||||||
@mock.patch.object(api, 'get_session',
|
@mock.patch.object(api, 'get_session',
|
||||||
return_value=mock.Mock(name='session'),)
|
return_value=mock.Mock(name='session'),)
|
||||||
@mock.patch('refstack.db.sqlalchemy.models.Product')
|
@mock.patch('refstack.db.sqlalchemy.models.Product')
|
||||||
@mock.patch.object(api, '_to_dict', side_effect=lambda x: x)
|
@mock.patch.object(api, '_to_dict', side_effect=lambda x, allowed_keys: x)
|
||||||
def test_product_get(self, mock_to_dict, mock_model, mock_get_session):
|
def test_product_get(self, mock_to_dict, mock_model, mock_get_session):
|
||||||
_id = 12345
|
_id = 12345
|
||||||
session = mock_get_session.return_value
|
session = mock_get_session.return_value
|
||||||
|
Loading…
Reference in New Issue
Block a user