Merge lp:~ricardokirkner/ols-store-tests/snap-purchases-api into lp:~ubuntuone-pqm-team/ols-store-tests/store-acceptance-tests

Proposed by Ricardo Kirkner
Status: Merged
Merged at revision: 33
Proposed branch: lp:~ricardokirkner/ols-store-tests/snap-purchases-api
Merge into: lp:~ubuntuone-pqm-team/ols-store-tests/store-acceptance-tests
Diff against target: 341 lines (+286/-4)
6 files modified
.bzrignore (+2/-0)
Makefile (+21/-3)
dependencies.txt (+1/-1)
requirements.txt (+1/-0)
tests/api/snap/test_snap_purchases_customers.py (+133/-0)
tests/api/snap/test_snap_purchases_orders.py (+128/-0)
To merge this branch: bzr merge lp:~ricardokirkner/ols-store-tests/snap-purchases-api
Reviewer Review Type Date Requested Status
Vincent Ladeuil (community) Approve
Ubuntu One PQM Team Pending
Review via email: mp+305946@code.launchpad.net

Commit message

added tests for new snap purchases api

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

make sure store-versions is called after the branch has been updated

33. By Ricardo Kirkner

use wheels for dependencies instead of hitting pypi

34. By Ricardo Kirkner

pass STRIPE_PUBLISHABLE_KEY to vm environment

Revision history for this message
Vincent Ladeuil (vila) wrote :

I didn't review the tests, for the "infra" bits, all look sane.

Thanks for the great work ;)

review: Approve
35. By Ricardo Kirkner

updated snap purchases api urls

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.bzrignore'
2--- .bzrignore 1970-01-01 00:00:00 +0000
3+++ .bzrignore 2016-09-19 13:38:27 +0000
4@@ -0,0 +1,2 @@
5+env
6+branches/
7
8=== modified file 'Makefile'
9--- Makefile 2016-09-19 12:16:07 +0000
10+++ Makefile 2016-09-19 13:38:27 +0000
11@@ -1,11 +1,28 @@
12 # Copyright (C) 2016 Canonical Ltd.
13
14+ENV = $(CURDIR)/env
15+PIP = pip3
16 PYTHON = python3
17 VM = store-acceptance-tests
18 VSSH = ols-vms shell ${VM}
19 TEST_TARGET ?= discover tests/api
20-
21-vm-setup: ols-vms.conf
22+PROJECT_NAME = ols-store-tests
23+WHEELS_DIR = branches/wheels
24+WHEELS_BRANCH_URL ?= lp:~ubuntuone-pqm-team/$(PROJECT_NAME)/dependencies
25+
26+bootstrap: $(ENV) wheels install-wheels
27+
28+$(ENV):
29+ pyvenv --clear --system-site-packages $(ENV)
30+
31+wheels:
32+ [ -d $(WHEELS_DIR) ] && (cd $(WHEELS_DIR) && bzr pull) || (bzr branch $(WHEELS_BRANCH_URL) $(WHEELS_DIR))
33+
34+install-wheels: ARGS=-r requirements.txt
35+install-wheels: $(ENV)
36+ $(PIP) install --find-links=$(WHEELS_DIR) --no-index $(ARGS)
37+
38+vm-setup: ols-vms.conf dependencies.txt
39 if [ `ols-vms status ${VM}` = 'RUNNING' ] ; then ols-vms stop ${VM} ; fi
40 ols-vms setup ${VM}
41 touch vm-setup
42@@ -30,7 +47,8 @@
43 TEST_USER_EMAIL=$(TEST_USER_EMAIL) \
44 TEST_USER_PASSWORD=$(TEST_USER_PASSWORD) \
45 TEST_USER_NAMESPACE=$(TEST_USER_NAMESPACE) \
46+ STRIPE_PUBLISHABLE_KEY=$(STRIPE_PUBLISHABLE_KEY) \
47 make api-tests'
48
49-api-tests:
50+api-tests: bootstrap
51 $(PYTHON) -u -m unittest $(TEST_TARGET)
52
53=== added directory 'branches'
54=== modified file 'dependencies.txt'
55--- dependencies.txt 2016-08-18 12:49:56 +0000
56+++ dependencies.txt 2016-09-19 13:38:27 +0000
57@@ -1,6 +1,6 @@
58 make
59 squashfs-tools
60 snapcraft
61+python3-pip
62 python3-pymacaroons
63 python3-requests
64-
65
66=== added file 'requirements.txt'
67--- requirements.txt 1970-01-01 00:00:00 +0000
68+++ requirements.txt 2016-09-19 13:38:27 +0000
69@@ -0,0 +1,1 @@
70+stripe==1.36.0
71
72=== added file 'tests/api/snap/test_snap_purchases_customers.py'
73--- tests/api/snap/test_snap_purchases_customers.py 1970-01-01 00:00:00 +0000
74+++ tests/api/snap/test_snap_purchases_customers.py 2016-09-19 13:38:27 +0000
75@@ -0,0 +1,133 @@
76+from __future__ import unicode_literals
77+
78+import json
79+import os
80+
81+import requests # fades
82+import stripe # fades
83+
84+from .helpers import (
85+ SCA_ROOT_URL,
86+ APITestCase,
87+ authenticate_with_macaroon,
88+)
89+
90+
91+def create_customer(stripe_token, auth=None):
92+ headers = {
93+ 'Content-Type': 'application/json',
94+ }
95+ if auth is not None:
96+ headers['Authorization'] = auth
97+ data = {}
98+ if stripe_token is not None:
99+ data['stripe_token'] = stripe_token
100+ url = '{}/purchases/v1/customers'.format(SCA_ROOT_URL)
101+ response = requests.post(url, data=json.dumps(data), headers=headers)
102+ return response
103+
104+
105+def get_stripe_token():
106+ stripe.api_key = os.getenv('STRIPE_PUBLISHABLE_KEY', None)
107+ token = stripe.Token.create(card={
108+ 'number': '4111111111111111',
109+ 'cvc': '1234',
110+ 'exp_year': 2032,
111+ 'exp_month': 12,
112+ })
113+ return token.id
114+
115+
116+def get_customer(auth=None):
117+ headers = {
118+ 'Content-Type': 'application/json',
119+ 'Cache-Control': 'no-cache',
120+ }
121+ if auth is not None:
122+ headers['Authorization'] = auth
123+ url = '{}/purchases/v1/customers/me'.format(SCA_ROOT_URL)
124+ response = requests.get(url, headers=headers)
125+ return response
126+
127+
128+class CreateCustomerTestCase(APITestCase):
129+
130+ @classmethod
131+ def setUpClass(cls):
132+ super(CreateCustomerTestCase, cls).setUpClass()
133+
134+ cls.auth = authenticate_with_macaroon()
135+
136+ def assert_invalid_request(self, response, message=None, extra=None):
137+ self.assertEqual(response.status_code, 400)
138+ body = response.json()
139+ if message is None:
140+ message = "The 'stripe_token' field is required."
141+ if extra is None:
142+ extra = {'field': 'stripe_token'}
143+ self.assertEqual(body, {
144+ 'error_list': [
145+ {'code': 'invalid-field',
146+ 'message': message,
147+ 'extra': extra},
148+ ]
149+ })
150+
151+ def assert_customer(self, response):
152+ self.assertEqual(response.status_code, 200)
153+ body = response.json()
154+ self.assertIn('accepted_tos_date', body)
155+ self.assertIn('latest_tos_date', body)
156+ self.assertIn('latest_tos_accepted', body)
157+
158+ def test_require_authentication(self):
159+ response = create_customer(stripe_token='token')
160+ self.assert_require_auth(response)
161+
162+ def test_create_customer_missing_token(self):
163+ response = create_customer(stripe_token=None, auth=self.auth)
164+ self.assert_invalid_request(response)
165+
166+ def test_create_customer_invalid_token(self):
167+ response = create_customer(stripe_token='', auth=self.auth)
168+ message = "The 'stripe_token' field can not be empty."
169+ self.assert_invalid_request(response, message)
170+
171+ def test_create_customer_bad_token(self):
172+ response = create_customer(stripe_token='invalid', auth=self.auth)
173+ message = "'invalid' is not a valid stripe_token."
174+ extra = {'field': 'stripe_token', 'value': 'invalid'}
175+ self.assert_invalid_request(response, message, extra)
176+
177+ def test_create_customer_success(self):
178+ token = get_stripe_token()
179+ response = create_customer(stripe_token=token, auth=self.auth)
180+ self.assert_customer(response)
181+
182+
183+class GetCustomerTestCase(APITestCase):
184+
185+ @classmethod
186+ def setUpClass(cls):
187+ super(GetCustomerTestCase, cls).setUpClass()
188+
189+ cls.auth = authenticate_with_macaroon()
190+
191+ def assert_customer(self, response):
192+ data = response.json()
193+ self.assertIn('latest_tos_date', data)
194+ self.assertIn('accepted_tos_date', data)
195+ self.assertIn('latest_tos_accepted', data)
196+
197+ def test_require_authentication(self):
198+ response = get_customer()
199+ self.assert_require_auth(response)
200+
201+ def test_get_customer_successful(self):
202+ response = get_customer(auth=self.auth)
203+ self.assert_success(response)
204+ self.assert_customer(response)
205+
206+ def test_get_customer_bad_auth(self):
207+ response = get_customer(auth='invalid')
208+ self.assert_require_auth(response)
209
210=== added file 'tests/api/snap/test_snap_purchases_orders.py'
211--- tests/api/snap/test_snap_purchases_orders.py 1970-01-01 00:00:00 +0000
212+++ tests/api/snap/test_snap_purchases_orders.py 2016-09-19 13:38:27 +0000
213@@ -0,0 +1,128 @@
214+from __future__ import unicode_literals
215+
216+import json
217+
218+import requests # fades
219+
220+from .helpers import (
221+ SCA_ROOT_URL,
222+ APITestCase,
223+ authenticate_with_macaroon,
224+)
225+from .test_snap_purchases_customers import (
226+ create_customer,
227+ get_stripe_token,
228+)
229+
230+
231+SNAP_PACKAGE_SNAP_ID = 'A0KkM9O8Aoht03uQqKwGB7JEZAbTPwnu'
232+
233+
234+def create_order(snap_id, currency=None, amount=None, auth=None):
235+ headers = {
236+ 'Content-Type': 'application/json',
237+ }
238+ if auth is not None:
239+ headers['Authorization'] = auth
240+ data = {}
241+ if snap_id is not None:
242+ data['snap_id'] = snap_id
243+ if currency is not None:
244+ data['currency'] = currency
245+ if amount is not None:
246+ data['amount'] = amount
247+ url = '{}/purchases/v1/orders'.format(SCA_ROOT_URL)
248+ response = requests.post(url, data=json.dumps(data), headers=headers)
249+ return response
250+
251+
252+def get_orders(auth=None):
253+ headers = {
254+ 'Content-Type': 'application/json',
255+ }
256+ if auth is not None:
257+ headers['Authorization'] = auth
258+ url = '{}/purchases/v1/orders'.format(SCA_ROOT_URL)
259+ response = requests.get(url, headers=headers)
260+ return response
261+
262+
263+class OrdersTestCase(APITestCase):
264+
265+ @classmethod
266+ def setUpClass(cls):
267+ super(OrdersTestCase, cls).setUpClass()
268+
269+ cls.auth = authenticate_with_macaroon(permissions=['package_purchase'])
270+
271+ def assert_order_data(self, order):
272+ self.assertEqual(order['snap_id'], SNAP_PACKAGE_SNAP_ID)
273+ self.assertEqual(order['state'], 'Complete')
274+ self.assertEqual(order['currency'], 'USD')
275+ self.assertIn('amount', order)
276+ self.assertIsNotNone(order['amount'])
277+
278+
279+class CreateOrderTestCase(OrdersTestCase):
280+
281+ def assert_invalid_request(self, response, message=None, extra=None):
282+ self.assertEqual(response.status_code, 400)
283+ body = response.json()
284+ if message is None:
285+ message = "The 'snap_id' field is required."
286+ if extra is None:
287+ extra = {'field': 'snap_id'}
288+ self.assertEqual(body, {
289+ 'error_list': [
290+ {'code': 'invalid-field',
291+ 'message': message,
292+ 'extra': extra}
293+ ]
294+ })
295+
296+ def assert_order(self, response):
297+ self.assertEqual(response.status_code, 200)
298+ body = response.json()
299+ self.assert_order_data(body)
300+
301+ def test_require_authentication(self):
302+ response = create_order(snap_id='snap-id')
303+ self.assert_require_auth(response)
304+
305+ def test_create_order_missing_snap_id(self):
306+ response = create_order(snap_id=None, auth=self.auth)
307+ self.assert_invalid_request(response)
308+
309+ def test_create_order_invalid_currency(self):
310+ response = create_order(snap_id='snap-id', currency='EUR',
311+ auth=self.auth)
312+ message = "'EUR' is not a valid currency."
313+ extra = {'field': 'currency', 'value': 'EUR'}
314+ self.assert_invalid_request(response, message, extra)
315+
316+ def test_create_order_success(self):
317+ token = get_stripe_token()
318+ response = create_customer(stripe_token=token, auth=self.auth)
319+ assert response.status_code == 200
320+ response = create_order(snap_id=SNAP_PACKAGE_SNAP_ID, auth=self.auth)
321+ self.assert_order(response)
322+
323+
324+class GetOrdersTestCase(OrdersTestCase):
325+
326+ def assert_orders(self, response):
327+ self.assertEqual(response.status_code, 200)
328+ body = response.json()
329+ self.assertIn('orders', body)
330+ orders = body['orders']
331+ if orders:
332+ order = body['orders'][-1]
333+ self.assert_order_data(order)
334+
335+ def test_require_authentication(self):
336+ response = get_orders()
337+ self.assert_require_auth(response)
338+
339+ def test_get_orders(self):
340+ response = get_orders(auth=self.auth)
341+ self.assert_orders(response)

Subscribers

People subscribed via source and target branches

to all changes: