Merge lp:~ricardokirkner/ols-store-tests/more-acceptance-tests into lp:~ubuntuone-pqm-team/ols-store-tests/store-acceptance-tests

Proposed by Ricardo Kirkner
Status: Merged
Merged at revision: 19
Proposed branch: lp:~ricardokirkner/ols-store-tests/more-acceptance-tests
Merge into: lp:~ubuntuone-pqm-team/ols-store-tests/store-acceptance-tests
Diff against target: 765 lines (+705/-3)
8 files modified
Makefile (+1/-1)
tests/api/cpi/helpers.py (+40/-2)
tests/api/cpi/test_channel.py (+56/-0)
tests/api/cpi/test_department.py (+82/-0)
tests/api/cpi/test_framework.py (+60/-0)
tests/api/cpi/test_highlight.py (+65/-0)
tests/api/cpi/test_metadata.py (+176/-0)
tests/api/cpi/test_package.py (+225/-0)
To merge this branch: bzr merge lp:~ricardokirkner/ols-store-tests/more-acceptance-tests
Reviewer Review Type Date Requested Status
James Tait (community) Approve
Matias Bordese (community) Approve
Review via email: mp+299342@code.launchpad.net

Commit message

added basic smoke tests for cpi APIs

added tests for following endpoints:

- package
- click metadata
- snap metadata
- highlights
- frameworks
- departments
- channels

To post a comment you must log in.
25. By Ricardo Kirkner

refactor tests to use constant

Revision history for this message
Matias Bordese (matiasb) wrote :

Looking good, added a few comments/questions.

review: Approve
26. By Ricardo Kirkner

fixes per review

Revision history for this message
Ricardo Kirkner (ricardokirkner) :
Revision history for this message
James Tait (jamestait) wrote :

Yep, looks good to me. I've made a couple of suggestions, but they are just that - this is good to land as-is, IMO.

As an aside, we're hard-coding some assumptions about URL structure (e.g. appending click-package-name or snap-package-id to /api/v1/package), which may not hold true longer-term. I think that's probably OK for these tests, since we *want* to know if URLs change, and I don't think *any* of the clients are actually parsing the links from the root resource anyway.

review: Approve
27. By Ricardo Kirkner

fixes per review

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Makefile'
--- Makefile 2016-07-05 14:42:00 +0000
+++ Makefile 2016-07-07 18:53:29 +0000
@@ -3,7 +3,7 @@
3PYTHON = python33PYTHON = python3
4VM = store-acceptance-tests4VM = store-acceptance-tests
5VSSH = ols-vms shell ${VM}5VSSH = ols-vms shell ${VM}
6TEST_TARGET := discover tests/api6TEST_TARGET ?= discover tests/api
77
8vm-setup: ols-vms.conf8vm-setup: ols-vms.conf
9 if [ `ols-vms status ${VM}` = 'RUNNING' ] ; then ols-vms stop ${VM} ; fi9 if [ `ols-vms status ${VM}` = 'RUNNING' ] ; then ols-vms stop ${VM} ; fi
1010
=== modified file 'tests/api/cpi/helpers.py'
--- tests/api/cpi/helpers.py 2016-06-28 19:20:09 +0000
+++ tests/api/cpi/helpers.py 2016-07-07 18:53:29 +0000
@@ -1,14 +1,52 @@
1import getpass
1import os2import os
2import unittest3import unittest
34
45
5CPI_ROOT_URL = os.getenv(6CPI_ROOT_URL = os.getenv(
6 'CPI_ROOT_URL', 'https://search.apps.staging.ubuntu.com')7 'CPI_ROOT_URL', 'https://search.apps.staging.ubuntu.com')
8SSO_ROOT_URL = os.getenv(
9 'SSO_ROOT_URL', 'https://login.staging.ubuntu.com')
10
11TEST_USER_EMAIL = os.getenv('TEST_USER_EMAIL', None)
12if TEST_USER_EMAIL is None:
13 TEST_USER_EMAIL = input('Test user email: ')
14TEST_USER_PASSWORD = os.getenv('TEST_USER_PASSWORD', None)
15if TEST_USER_PASSWORD is None:
16 TEST_USER_PASSWORD = getpass.getpass('Test user password: ')
17
18CLICK_PACKAGE_NAME = 'demo37.ricardokirkner'
19SNAP_PACKAGE_NAME = 'hello-world'
20SNAP_PACKAGE_CHANNEL = 'stable'
21SNAP_PACKAGE_REVISION = 6
22SNAP_PACKAGE_SNAP_ID = 'JtwEnisYi8Mmk51vNLZPSOwSOFLwGdhs'
23PRIVATE_SNAP_PACKAGE_NAME = 'ricardokirkner-test1'
24PRIVATE_SNAP_PACKAGE_SNAP_ID = 'qrwoXeYOXAZla2ga3XtBSogV1vAUKqZh'
25PRIVATE_SNAP_PACKAGE_CHANNEL = 'stable'
26PRIVATE_SNAP_PACKAGE_REVISION = 1
727
828
9class APITestCase(unittest.TestCase):29class APITestCase(unittest.TestCase):
1030
11 def assert_success(self, response):31 def assert_success(self, response, content_type='application/hal+json'):
12 self.assertEqual(response.status_code, 200)32 self.assertEqual(response.status_code, 200)
13 self.assertEqual(response.headers['Content-Type'],33 self.assertEqual(response.headers['Content-Type'],
14 'application/hal+json')34 content_type)
35
36 def assert_not_found(self, response, message=None):
37 self.assertEqual(response.status_code, 404)
38 self.assertEqual(response.headers['Content-Type'],
39 'application/hal+json')
40 self.assertEqual(response.json(), {
41 'result': 'error',
42 'errors': [message or 'Not found'],
43 })
44
45 def assert_bad_request(self, response, message):
46 self.assertEqual(response.status_code, 400)
47 self.assertEqual(response.headers['Content-Type'],
48 'application/hal+json')
49 self.assertEqual(response.json(), {
50 'result': 'error',
51 'errors': [message],
52 })
1553
=== added file 'tests/api/cpi/test_channel.py'
--- tests/api/cpi/test_channel.py 1970-01-01 00:00:00 +0000
+++ tests/api/cpi/test_channel.py 2016-07-07 18:53:29 +0000
@@ -0,0 +1,56 @@
1import requests
2
3from .helpers import (
4 CPI_ROOT_URL,
5 APITestCase,
6)
7
8
9def get_channels():
10 url = '{}/api/v1/channels'.format(CPI_ROOT_URL)
11 response = requests.get(url)
12 return response
13
14
15def get_channel(name):
16 url = '{}/api/v1/channels/{}'.format(CPI_ROOT_URL, name)
17 response = requests.get(url)
18 return response
19
20
21class ChannelsTestCase(APITestCase):
22
23 def assert_channels(self, response):
24 body = response.json()
25 # assert generic embedded data structure
26 self.assertIn('_embedded', body)
27 self.assertIn('clickindex:channel', body['_embedded'])
28 # assert there is at least one result
29 self.assertGreater(len(body['_embedded']['clickindex:channel']), 0)
30 # assert result data structure
31 channel_data = body['_embedded']['clickindex:channel']
32 channel_names = ('stable', 'candidate', 'beta', 'edge')
33 for item, name in zip(channel_data, channel_names):
34 self._assert_channel_data(item, name=name)
35
36 def assert_channel(self, response, name):
37 body = response.json()
38 # assert result data structure
39 self._assert_channel_data(body, name=name)
40
41 def _assert_channel_data(self, data, name=None):
42 self.assertIn('promotion_order', data)
43 self.assertIn('display_name', data)
44 self.assertIn('name', data)
45 if name is not None:
46 self.assertEqual(data['name'], name)
47
48 def test_get_channels(self):
49 response = get_channels()
50 self.assert_success(response)
51 self.assert_channels(response)
52
53 def test_get_channel(self):
54 response = get_channel('edge')
55 self.assert_success(response)
56 self.assert_channel(response, 'edge')
057
=== added file 'tests/api/cpi/test_department.py'
--- tests/api/cpi/test_department.py 1970-01-01 00:00:00 +0000
+++ tests/api/cpi/test_department.py 2016-07-07 18:53:29 +0000
@@ -0,0 +1,82 @@
1import requests
2
3from .helpers import (
4 CPI_ROOT_URL,
5 APITestCase,
6)
7
8
9def get_departments(include_subdepartments=None):
10 url = '{}/api/v1/departments'.format(CPI_ROOT_URL)
11 if include_subdepartments is True:
12 url += '?include_subdepartments=true'
13 elif include_subdepartments is False:
14 url += '?include_subdepartments=false'
15 response = requests.get(url)
16 return response
17
18
19def get_department(slug):
20 url = '{}/api/v1/departments/{}'.format(CPI_ROOT_URL, slug)
21 response = requests.get(url)
22 return response
23
24
25class DepartmentsTestCase(APITestCase):
26
27 def assert_departments(self, response):
28 body = response.json()
29 # assert generic embedded data structure
30 self.assertIn('_embedded', body)
31 self.assertIn('clickindex:department', body['_embedded'])
32 # assert there is at least one result
33 self.assertGreater(len(body['_embedded']['clickindex:department']), 0)
34 # assert result data structure
35 item = body['_embedded']['clickindex:department'][0]
36 self._assert_department_data(item)
37
38 def assert_department(self, response, slug):
39 body = response.json()
40 # assert result data structure
41 self._assert_department_data(body, slug=slug)
42
43 def _assert_department_data(self, data, slug=None):
44 self.assertIn('has_children', data)
45 self.assertIn('name', data)
46 self.assertIn('slug', data)
47 if slug is not None:
48 self.assertEqual(data['slug'], slug)
49
50 def find_subdepartment(self, response, department, slug):
51 body = response.json()
52 for item in body.get('_embedded', {}).get('clickindex:department', []):
53 department_match = item.get('slug') == department
54 if department_match and item.get('has_children', False):
55 for subitem in item.get('_embedded', {}).get(
56 'clickindex:department', []):
57 if subitem.get('slug') == slug:
58 return subitem
59
60 def test_get_departments(self):
61 response = get_departments()
62 self.assert_success(response)
63 self.assert_departments(response)
64
65 def test_get_department(self):
66 response = get_department(slug='games')
67 self.assert_success(response)
68 self.assert_department(response, slug='games')
69
70 def test_include_subdepartments_by_default(self):
71 response = get_departments()
72 self.assert_success(response)
73 department = self.find_subdepartment(
74 response, 'games', slug='fps')
75 self.assertIsNotNone(department)
76 self._assert_department_data(department, slug='fps')
77
78 def test_exclude_subdepartments(self):
79 response = get_departments(include_subdepartments=False)
80 self.assert_success(response)
81 department = self.find_subdepartment(response, 'games', slug='fps')
82 self.assertIsNone(department)
083
=== added file 'tests/api/cpi/test_framework.py'
--- tests/api/cpi/test_framework.py 1970-01-01 00:00:00 +0000
+++ tests/api/cpi/test_framework.py 2016-07-07 18:53:29 +0000
@@ -0,0 +1,60 @@
1import requests
2
3from .helpers import (
4 CPI_ROOT_URL,
5 APITestCase,
6)
7
8
9def get_frameworks():
10 url = '{}/api/v1/frameworks'.format(CPI_ROOT_URL)
11 response = requests.get(url)
12 return response
13
14
15def get_framework(name):
16 url = '{}/api/v1/frameworks/{}'.format(CPI_ROOT_URL, name)
17 response = requests.get(url)
18 return response
19
20
21class FrameworksTestCase(APITestCase):
22
23 def assert_frameworks(self, response):
24 body = response.json()
25 # assert generic embedded data structure
26 self.assertIn('_embedded', body)
27 self.assertIn('clickindex:framework', body['_embedded'])
28 # assert there is at least one result
29 self.assertGreater(len(body['_embedded']['clickindex:framework']), 0)
30 # assert result data structure
31 item = body['_embedded']['clickindex:framework'][0]
32 self._assert_framework_data(item)
33
34 def assert_framework(self, response, name):
35 body = response.json()
36 # assert result data structure
37 self._assert_framework_data(body, name=name)
38
39 def _assert_framework_data(self, data, name=None):
40 self.assertIn('enable_unauthenticated_downloads', data)
41 self.assertIn('policy_vendor', data)
42 self.assertIn('policy_version', data)
43 self.assertIn('state', data)
44 self.assertIn('name', data)
45 if name is not None:
46 self.assertEqual(data['name'], name)
47
48 def test_get_frameworks(self):
49 response = get_frameworks()
50 self.assert_success(response)
51 self.assert_frameworks(response)
52
53 def test_get_framework(self):
54 response = get_framework(name='ubuntu-sdk-15.04')
55 self.assert_success(response)
56 self.assert_framework(response, name='ubuntu-sdk-15.04')
57
58 def test_get_framework_not_found(self):
59 response = get_framework(name='invalid')
60 self.assert_not_found(response, message='No such framework')
061
=== added file 'tests/api/cpi/test_highlight.py'
--- tests/api/cpi/test_highlight.py 1970-01-01 00:00:00 +0000
+++ tests/api/cpi/test_highlight.py 2016-07-07 18:53:29 +0000
@@ -0,0 +1,65 @@
1import requests
2
3from .helpers import (
4 CPI_ROOT_URL,
5 APITestCase,
6)
7
8
9def get_highlights():
10 url = '{}/api/v1/highlights'.format(CPI_ROOT_URL)
11 response = requests.get(url)
12 return response
13
14
15def get_highlight(slug):
16 url = '{}/api/v1/highlights/{}'.format(CPI_ROOT_URL, slug)
17 response = requests.get(url)
18 return response
19
20
21class HighlightsTestCase(APITestCase):
22
23 def assert_highlights(self, response):
24 body = response.json()
25 # assert generic embedded data structure
26 self.assertIn('_embedded', body)
27 self.assertIn('clickindex:highlight', body['_embedded'])
28 # assert there is at least one result
29 self.assertGreater(len(body['_embedded']['clickindex:highlight']), 0)
30 # assert result data structure
31 item = body['_embedded']['clickindex:highlight'][0]
32 self._assert_highlight_data(item)
33
34 def assert_highlight(self, response, slug):
35 body = response.json()
36 # assert result data structure
37 self._assert_highlight_data(body, slug=slug)
38
39 def _assert_highlight_data(self, data, slug=None):
40 self.assertIn('name', data)
41 self.assertIn('description', data)
42 self.assertIn('country_code', data)
43 self.assertIn('slug', data)
44 if slug is not None:
45 self.assertEqual(data['slug'], slug)
46
47 def test_get_highlights(self):
48 response = get_highlights()
49 self.assert_success(response)
50 self.assert_highlights(response)
51
52 def test_get_highlight(self):
53 response = get_highlight(slug='top-apps')
54 self.assert_success(response)
55 self.assert_highlight(response, slug='top-apps')
56
57 def test_get_highlight_not_found(self):
58 response = get_highlight(slug='missing')
59 self.assert_not_found(
60 response, message="No such highlight u'missing'")
61
62 def test_get_highlight_invalid_slug(self):
63 response = get_highlight(slug='top-apps:en')
64 self.assert_not_found(
65 response, message="No such highlight u'top-apps:en'")
066
=== added file 'tests/api/cpi/test_metadata.py'
--- tests/api/cpi/test_metadata.py 1970-01-01 00:00:00 +0000
+++ tests/api/cpi/test_metadata.py 2016-07-07 18:53:29 +0000
@@ -0,0 +1,176 @@
1import json
2
3import requests
4
5from .helpers import (
6 CLICK_PACKAGE_NAME,
7 CPI_ROOT_URL,
8 SNAP_PACKAGE_SNAP_ID,
9 APITestCase,
10)
11
12
13def get_click_metadata(names=None, method='get'):
14 url = '{}/api/v1/click-metadata'.format(CPI_ROOT_URL)
15 if method == 'get':
16 if names is not None:
17 url += '?' + '&'.join('name=' + name for name in names)
18 response = requests.get(url)
19 elif method == 'post':
20 data = {}
21 if names is not None:
22 data['name'] = names
23 response = requests.post(url, data=json.dumps(data),
24 headers={'Content-Type': 'application/json'})
25 else:
26 raise ValueError('invalid method: %s' % method)
27 return response
28
29
30class ClickMetadataTestCase(APITestCase):
31
32 def assert_click_metadata(self, response, name):
33 body = response.json()
34 self.assertEqual(len(body), 1)
35 # assert result data structure
36 self._assert_package_data(body[0], name=name)
37
38 def _assert_package_data(self, data, name):
39 self.assertIn('anon_download_url', data)
40 self.assertIn('binary_filesize', data)
41 self.assertIn('changelog', data)
42 self.assertIn('channel', data)
43 self.assertIn('content', data)
44 self.assertIn('department', data)
45 self.assertIn('download_sha512', data)
46 self.assertIn('download_url', data)
47 self.assertIn('icon_url', data)
48 self.assertIn('name', data)
49 self.assertIn('origin', data)
50 self.assertIn('revision', data)
51 self.assertIn('status', data)
52 self.assertIn('summary', data)
53 self.assertIn('title', data)
54 self.assertIn('version', data)
55 self.assertEqual(data['name'], name)
56
57 def test_get_click_metadata(self):
58 response = get_click_metadata(names=[CLICK_PACKAGE_NAME])
59 self.assert_success(response, content_type='application/json')
60 self.assert_click_metadata(response, name=CLICK_PACKAGE_NAME)
61
62 def test_get_click_metadata_no_packages(self):
63 response = get_click_metadata()
64 self.assert_bad_request(
65 response,
66 message='Package names must be specified in parameter "name".')
67
68 def test_get_click_metadata_via_post(self):
69 response = get_click_metadata(
70 names=[CLICK_PACKAGE_NAME], method='post')
71 self.assert_success(response, content_type='application/json')
72 self.assert_click_metadata(response, name=CLICK_PACKAGE_NAME)
73
74 def test_get_click_metadata_no_packages_via_post(self):
75 response = get_click_metadata(method='post')
76 self.assert_bad_request(
77 response,
78 message='Package names must be specified in parameter "name".')
79
80 def test_get_click_metadata_bad_request_via_post(self):
81 url = '{}/api/v1/click-metadata'.format(CPI_ROOT_URL)
82 response = requests.post(url, data='invalid data',
83 headers={'Content-Type': 'application/json'})
84 self.assert_bad_request(
85 response, message='No JSON object could be decoded')
86
87
88def get_metadata(snaps=None, fields=None):
89 url = '{}/api/v1/metadata'.format(CPI_ROOT_URL)
90 data = {}
91 if snaps is not None:
92 data['snaps'] = snaps
93 if fields is not None:
94 data['fields'] = fields
95 response = requests.post(url, data=json.dumps(data),
96 headers={'Content-Type': 'application/json'})
97 return response
98
99
100class MetadataTestCase(APITestCase):
101
102 def assert_metadata(self, response, fields=None, snap_id=None):
103 body = response.json()
104 # assert generic embedded data structure
105 self.assertIn('_embedded', body)
106 self.assertIn('clickindex:package', body['_embedded'])
107 # assert there is at least one result
108 self.assertGreater(len(body['_embedded']['clickindex:package']), 0)
109 # assert result data structure
110 item = body['_embedded']['clickindex:package'][0]
111 self._assert_package_data(item, fields=fields, snap_id=snap_id)
112
113 def _assert_package_data(self, data, fields=None, snap_id=None):
114 if fields is None:
115 fields = [
116 'anon_download_url',
117 'binary_filesize',
118 'changelog',
119 'channel',
120 'content',
121 'department',
122 'download_sha512',
123 'download_url',
124 'icon_url',
125 'name',
126 'origin',
127 'package_name',
128 'plugs',
129 'revision',
130 'slots',
131 'snap_id',
132 'status',
133 'summary',
134 'title',
135 'version',
136 ]
137 expected = fields + ['_links']
138 self.assertEqual(set(data.keys()), set(expected))
139 if snap_id is not None:
140 self.assertEqual(data['snap_id'], snap_id)
141
142 def assert_no_results(self, response):
143 body = response.json()
144 self._assert_package_data(body, fields=[])
145
146 def test_get_metadata(self):
147 response = get_metadata(
148 snaps=[{'snap_id': SNAP_PACKAGE_SNAP_ID}])
149 self.assert_success(response)
150 self.assert_metadata(response, snap_id=SNAP_PACKAGE_SNAP_ID)
151
152 def test_get_metadata_no_snaps(self):
153 response = get_metadata()
154 self.assert_bad_request(
155 response,
156 message='Packages must be specified in parameter "snaps".')
157
158 def test_get_metadata_missing_snap_id(self):
159 response = get_metadata(snaps=[{}])
160 self.assert_bad_request(
161 response, message='Missing snap_id for snap.')
162
163 def test_get_metadata_filter_fields(self):
164 fields = ['channel', 'revision', 'snap_id']
165 response = get_metadata(
166 snaps=[{'snap_id': SNAP_PACKAGE_SNAP_ID}],
167 fields=fields)
168 self.assert_success(response)
169 self.assert_metadata(
170 response, fields=fields, snap_id=SNAP_PACKAGE_SNAP_ID)
171
172 def test_get_metadata_invalid_package(self):
173 response = get_metadata(
174 snaps=[{'snap_id': 'invalid'}])
175 self.assert_success(response)
176 self.assert_no_results(response)
0177
=== added file 'tests/api/cpi/test_package.py'
--- tests/api/cpi/test_package.py 1970-01-01 00:00:00 +0000
+++ tests/api/cpi/test_package.py 2016-07-07 18:53:29 +0000
@@ -0,0 +1,225 @@
1import json
2
3import requests
4import requests_oauthlib
5
6from .helpers import (
7 CPI_ROOT_URL,
8 PRIVATE_SNAP_PACKAGE_CHANNEL,
9 PRIVATE_SNAP_PACKAGE_NAME,
10 PRIVATE_SNAP_PACKAGE_REVISION,
11 PRIVATE_SNAP_PACKAGE_SNAP_ID,
12 SNAP_PACKAGE_CHANNEL,
13 SNAP_PACKAGE_NAME,
14 SNAP_PACKAGE_REVISION,
15 SSO_ROOT_URL,
16 TEST_USER_EMAIL,
17 TEST_USER_PASSWORD,
18 APITestCase,
19)
20
21
22def get_package(package_id, channel=None, revision=None, auth=False):
23 url = '{}/api/v1/package/{}'.format(CPI_ROOT_URL, package_id)
24 if channel is not None:
25 url += '/{}'.format(channel)
26 elif revision is not None:
27 url += '/{}'.format(revision)
28 if auth:
29 # use client as contextmanager to ensure ssl socket is closed
30 # afterwards
31 with get_oauth_client() as client:
32 response = client.get(url)
33 else:
34 response = requests.get(url)
35 return response
36
37
38def get_oauth_token_data(email, password):
39 url = '{}/api/v2/tokens/oauth'.format(SSO_ROOT_URL)
40 data = {
41 'email': email,
42 'password': password,
43 'token_name': 'store-acceptance-tests',
44 }
45 headers = {
46 'Content-Type': 'application/json',
47 'Accept': 'application/json',
48 }
49 response = requests.post(url, data=json.dumps(data), headers=headers)
50 assert response.ok, 'Failed to get oauth token: %r' % response.content
51
52 data = response.json()
53 return {
54 'client_key': data['consumer_key'],
55 'client_secret': data['consumer_secret'],
56 'resource_owner_key': data['token_key'],
57 'resource_owner_secret': data['token_secret'],
58 }
59
60
61def get_oauth_client():
62 credentials = get_oauth_token_data(TEST_USER_EMAIL, TEST_USER_PASSWORD)
63 client = requests_oauthlib.OAuth1Session(**credentials)
64 client.headers.update({
65 'Content-Type': 'application/json',
66 'Cache-Control': 'no-cache',
67 })
68 return client
69
70
71class PackageBaseTestCase(APITestCase):
72
73 def assert_package(self, response, snap_id=None, name=None,
74 channel=None, revision=None, exclude_fields=None):
75 body = response.json()
76 fields = [
77 'alias',
78 'allow_unauthenticated',
79 'anon_download_url',
80 'architecture',
81 'binary_filesize',
82 'blacklist_country_codes',
83 'changelog',
84 'channel',
85 'channels',
86 'click_framework',
87 'click_version',
88 'company_name',
89 'confinement',
90 'content',
91 'date_published',
92 'department',
93 'description',
94 'developer_id',
95 'developer_name',
96 'download_sha512',
97 'download_url',
98 'epoch',
99 'framework',
100 'icon_url',
101 'icon_urls',
102 'id',
103 'is_published',
104 'keywords',
105 'last_updated',
106 'license',
107 'name',
108 'origin',
109 'package_name',
110 'plugs',
111 'price',
112 'prices',
113 'promoted',
114 'publisher',
115 'ratings_average',
116 'release',
117 'revision',
118 'screenshot_url',
119 'screenshot_urls',
120 'slots',
121 'snap_id',
122 'status',
123 'summary',
124 'support_url',
125 'terms_of_service',
126 'title',
127 'version',
128 'video_urls',
129 'website',
130 'whitelist_country_codes',
131 ]
132 # assert result data structure
133 expected = set(fields + ['_links'])
134 if exclude_fields:
135 expected = expected - set(exclude_fields)
136 self.assertEqual(set(body.keys()), expected)
137 if snap_id is not None:
138 self.assertEqual(body['snap_id'], snap_id)
139 if name is not None:
140 self.assertEqual(body['package_name'], name)
141 if channel is not None:
142 self.assertEqual(body['channel'], channel)
143 self.assertIn(channel, body['channels'])
144 if revision is not None:
145 self.assertEqual(body['revision'], revision)
146
147
148class PackageTestCase(PackageBaseTestCase):
149
150 def test_get_package(self):
151 response = get_package(SNAP_PACKAGE_NAME)
152 self.assert_success(response)
153 self.assert_package(response, name=SNAP_PACKAGE_NAME)
154
155 def test_get_private_package_when_not_authorized(self):
156 response = get_package(PRIVATE_SNAP_PACKAGE_SNAP_ID)
157 self.assert_not_found(response, message='No such package')
158
159 def test_get_private_package_when_authorized(self):
160 response = get_package(PRIVATE_SNAP_PACKAGE_SNAP_ID, auth=True)
161 self.assert_success(response)
162 self.assert_package(
163 response, snap_id=PRIVATE_SNAP_PACKAGE_SNAP_ID,
164 name=PRIVATE_SNAP_PACKAGE_NAME)
165
166 def test_get_package_not_found(self):
167 response = get_package('missing')
168 self.assert_not_found(response, message='No such package')
169
170
171class ChannelPackageTestCase(PackageBaseTestCase):
172
173 def test_get_channel_package(self):
174 response = get_package(SNAP_PACKAGE_NAME, channel=SNAP_PACKAGE_CHANNEL)
175 self.assert_success(response)
176 self.assert_package(response, name=SNAP_PACKAGE_NAME,
177 channel=SNAP_PACKAGE_CHANNEL)
178
179 def test_get_private_channel_package_when_not_authorized(self):
180 response = get_package(PRIVATE_SNAP_PACKAGE_SNAP_ID,
181 channel=PRIVATE_SNAP_PACKAGE_CHANNEL)
182 self.assert_not_found(response, message='No such package')
183
184 def test_get_private_channel_package_when_authorized(self):
185 response = get_package(PRIVATE_SNAP_PACKAGE_SNAP_ID,
186 channel=PRIVATE_SNAP_PACKAGE_CHANNEL, auth=True)
187 self.assert_success(response)
188 self.assert_package(
189 response, snap_id=PRIVATE_SNAP_PACKAGE_SNAP_ID,
190 name=PRIVATE_SNAP_PACKAGE_NAME, channel=PRIVATE_SNAP_PACKAGE_CHANNEL)
191
192 def test_get_channel_package_not_found(self):
193 response = get_package('missing', channel='stable')
194 self.assert_not_found(response, message='No such package')
195
196 def test_get_channel_package_wrong_channel(self):
197 response = get_package(SNAP_PACKAGE_NAME, channel='missing')
198 self.assert_not_found(response, message='No such package')
199
200
201class PackageRevisionTestCase(PackageBaseTestCase):
202
203 def test_get_package_revision(self):
204 response = get_package(SNAP_PACKAGE_NAME, revision=SNAP_PACKAGE_REVISION)
205 self.assert_success(response)
206 self.assert_package(
207 response, name=SNAP_PACKAGE_NAME, revision=SNAP_PACKAGE_REVISION,
208 exclude_fields=['channel'])
209
210 def test_get_private_package_revision_when_not_authorized(self):
211 response = get_package(PRIVATE_SNAP_PACKAGE_SNAP_ID,
212 revision=PRIVATE_SNAP_PACKAGE_REVISION)
213 self.assert_not_found(response, message='No such package')
214
215 def test_get_private_package_when_authorized(self):
216 response = get_package(PRIVATE_SNAP_PACKAGE_SNAP_ID,
217 revision=PRIVATE_SNAP_PACKAGE_REVISION, auth=True)
218 self.assert_success(response)
219 self.assert_package(
220 response, snap_id=PRIVATE_SNAP_PACKAGE_SNAP_ID,
221 name=PRIVATE_SNAP_PACKAGE_NAME, exclude_fields=['channel'])
222
223 def test_get_package_revision_not_found(self):
224 response = get_package(SNAP_PACKAGE_NAME, revision=-1)
225 self.assert_not_found(response, message='No such package')

Subscribers

People subscribed via source and target branches

to all changes: