Skip to content

Commit b3df11a

Browse files
committed
Added tests, fixed a few bugs along the way :)
1 parent 1874315 commit b3df11a

9 files changed

Lines changed: 246 additions & 12 deletions

File tree

Makefile

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: clean clean-pyc clean-build help
1+
.PHONY: clean clean-test clean-pyc clean-build help
22
.DEFAULT_GOAL := help
33
define BROWSER_PYSCRIPT
44
import os, webbrowser, sys
@@ -26,7 +26,7 @@ BROWSER := python -c "$$BROWSER_PYSCRIPT"
2626
help:
2727
@python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)
2828

29-
clean: clean-build clean-pyc ## remove all build, test, coverage and Python artifacts
29+
clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts
3030

3131
clean-build: ## remove build artifacts
3232
rm -fr build/
@@ -41,6 +41,26 @@ clean-pyc: ## remove Python file artifacts
4141
find . -name '*~' -exec rm -f {} +
4242
find . -name '__pycache__' -exec rm -fr {} +
4343

44+
clean-test: ## remove test and coverage artifacts
45+
rm -fr .tox/
46+
rm -f .coverage
47+
rm -fr htmlcov/
48+
49+
lint: ## check style with flake8
50+
flake8 python_wpapi tests
51+
52+
test: ## run tests quickly with the default Python
53+
py.test
54+
55+
test-all: ## run tests on every Python version with tox
56+
tox
57+
58+
coverage: ## check code coverage quickly with the default Python
59+
coverage run --source python_wpapi -m pytest
60+
coverage report -m
61+
coverage html
62+
$(BROWSER) htmlcov/index.html
63+
4464
release: clean ## package and upload a release
4565
python setup.py sdist upload
4666
python setup.py bdist_wheel upload

README.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,15 @@ Simple wrapper around the Wordpress REST API
1919
Features
2020
--------
2121

22-
* TODO
22+
* Will soon work on some documentation
23+
24+
Tests
25+
--------
26+
27+
.. code-block::
28+
```
29+
make test
30+
```
2331
2432
Credits
2533
---------

python_wpapi/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
__author__ = """Lucas Lobosque"""
44
__email__ = '[email protected]'
5-
__version__ = '0.1.0'
5+
__version__ = '0.2.0'

python_wpapi/errors.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ def __init__(self, status_code, code='', message='', data={}):
1010
def factory(response):
1111
status_code = response.status_code
1212
payload = response.json()
13-
code = payload['code']
14-
message = payload['message']
15-
data = payload['data']
13+
code = payload.get('code')
14+
message = payload.get('message')
15+
data = payload.get('data')
1616
if status_code == 400:
1717
return BadRequestWpApiError(code, message, data)
1818
elif status_code == 401:
@@ -30,9 +30,9 @@ def __init__(self, code='', message='', data={}):
3030
super(BadRequestWpApiError, self).__init__(400, code, message, data)
3131

3232

33-
class UnauthorizedApiErro(WpApiError):
33+
class UnauthorizedWpApiError(WpApiError):
3434
def __init__(self, code='', message='', data={}):
35-
super(NotFoundWpApiError, self).__init__(401, code, message, data)
35+
super(UnauthorizedWpApiError, self).__init__(401, code, message, data)
3636

3737

3838
class ForbiddenWpApiError(WpApiError):

python_wpapi/python_wpapi.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
import requests
3-
from errors import WpApiError
3+
from python_wpapi.errors import WpApiError
44

55

66
class WpApi():
@@ -24,7 +24,7 @@ def _request(self, endpoint, method='GET', headers={}, **kwargs):
2424
auth=self.auth,
2525
params=params,
2626
json=data,
27-
headers = headers
27+
headers=headers
2828
)
2929
if not response.status_code // 100 == 2:
3030
error = WpApiError.factory(response)
@@ -45,7 +45,7 @@ def create_post(self, **data):
4545

4646
def update_post(self, id, **data):
4747
endpoint = '{}/posts/{}'.format(self.base_url, id)
48-
return self._request(endpoint, data)
48+
return self._request(endpoint, method='POST', **data)
4949

5050
def get_medias(self):
5151
endpoint = '{}/media'.format(self.base_url)
@@ -66,3 +66,7 @@ def get_user(self, id):
6666
def get_taxonomies(self, type=None):
6767
endpoint = '{}/taxonomies'.format(self.base_url)
6868
return self._request(endpoint, type=type)
69+
70+
def get_taxonomy(self, slug):
71+
endpoint = '{}/taxonomies/{}'.format(self.base_url, slug)
72+
return self._request(endpoint)

requirements_dev.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ flake8==2.6.0
66
tox==2.3.1
77
coverage==4.1
88
Sphinx==1.4.8
9+
pytest==2.9.2
10+
mock==2.0.0
11+
requests==2.12.1

tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# -*- coding: utf-8 -*-

tests/test_python_wpapi.py

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
"""
5+
test_python_wpapi
6+
----------------------------------
7+
8+
Tests for `python_wpapi` module.
9+
"""
10+
11+
import pytest
12+
13+
from mock import patch
14+
from mock import Mock
15+
from python_wpapi import python_wpapi
16+
from python_wpapi import errors
17+
18+
19+
@pytest.fixture
20+
def api():
21+
"""Sample pytest fixture.
22+
See more at: http://doc.pytest.org/en/latest/fixture.html
23+
"""
24+
# import requests
25+
# return requests.get('https://github.com/audreyr/cookiecutter-pypackage')
26+
return python_wpapi.WpApi('http://base.url')
27+
28+
29+
def test_strip_slash():
30+
"""Verifies that the same base_url is generated if
31+
a trailing slash is added or not.
32+
"""
33+
api1 = python_wpapi.WpApi('http://base.url')
34+
api2 = python_wpapi.WpApi('http://base.url/')
35+
assert api1.base_url == api2.base_url
36+
37+
def test_auth():
38+
"""Check the possible self.auth combinations.
39+
"""
40+
api1 = python_wpapi.WpApi('http://base.url')
41+
api2 = python_wpapi.WpApi('http://base.url', user='User')
42+
api3 = python_wpapi.WpApi('http://base.url', user='User', password='Password')
43+
assert api1.auth == None
44+
assert api2.auth == ('User', None)
45+
assert api3.auth == ('User', 'Password')
46+
47+
@patch.object(python_wpapi.WpApi, '_request')
48+
def test_get_posts(mock, api):
49+
api.get_posts()
50+
mock.assert_called_with('http://base.url/wp-json/wp/v2/posts')
51+
52+
@patch.object(python_wpapi.WpApi, '_request')
53+
def test_get_post(mock, api):
54+
api.get_post(3)
55+
mock.assert_called_with('http://base.url/wp-json/wp/v2/posts/3')
56+
57+
@patch.object(python_wpapi.WpApi, '_request')
58+
def test_create_post(mock, api):
59+
api.create_post(title='Title Here', content='Content Here')
60+
kws = {
61+
'title': 'Title Here',
62+
'content': 'Content Here'
63+
}
64+
mock.assert_called_with('http://base.url/wp-json/wp/v2/posts',
65+
method='POST', **kws)
66+
67+
@patch.object(python_wpapi.WpApi, '_request')
68+
def test_update_post(mock, api):
69+
api.update_post(id=5, title='Updated')
70+
kws = {
71+
'title': 'Updated',
72+
}
73+
mock.assert_called_with('http://base.url/wp-json/wp/v2/posts/5',
74+
method='POST', **kws)
75+
76+
@patch.object(python_wpapi.WpApi, '_request')
77+
def test_get_medias(mock, api):
78+
api.get_medias()
79+
mock.assert_called_with('http://base.url/wp-json/wp/v2/media')
80+
81+
@patch.object(python_wpapi.WpApi, '_request')
82+
def test_get_media(mock, api):
83+
api.get_media(5)
84+
mock.assert_called_with('http://base.url/wp-json/wp/v2/media/5')
85+
86+
@patch.object(python_wpapi.WpApi, '_request')
87+
def test_get_users(mock, api):
88+
api.get_users()
89+
mock.assert_called_with('http://base.url/wp-json/wp/v2/users')
90+
91+
@patch.object(python_wpapi.WpApi, '_request')
92+
def test_get_user(mock, api):
93+
res = api.get_user(1)
94+
mock.assert_called_with('http://base.url/wp-json/wp/v2/users/1')
95+
96+
@patch.object(python_wpapi.WpApi, '_request')
97+
def test_get_taxonomies(mock, api):
98+
api.get_taxonomies()
99+
mock.assert_called_with('http://base.url/wp-json/wp/v2/taxonomies', type=None)
100+
101+
api.get_taxonomies(type='slug')
102+
mock.assert_called_with('http://base.url/wp-json/wp/v2/taxonomies', type='slug')
103+
104+
@patch.object(python_wpapi.WpApi, '_request')
105+
def test_get_taxonomie(mock, api):
106+
api.get_taxonomy('slug')
107+
mock.assert_called_with('http://base.url/wp-json/wp/v2/taxonomies/slug')
108+
109+
@patch.object(python_wpapi.requests, 'request')
110+
def test__request_get(mock, api):
111+
mock.return_value.json.return_value = {}
112+
mock.return_value.status_code = 200
113+
114+
api._request('endpoint', arg1='value')
115+
mock.assert_called_with('GET',
116+
'endpoint',
117+
auth=api.auth,
118+
params={'arg1': 'value'},
119+
json={},
120+
headers={}
121+
)
122+
123+
@patch.object(python_wpapi.requests, 'request')
124+
def test__request_post(mock, api):
125+
mock.return_value.json.return_value = {}
126+
mock.return_value.status_code = 200
127+
128+
api._request('endpoint', method='POST', arg1='value',
129+
headers={'header1': 'header2'})
130+
mock.assert_called_with('POST',
131+
'endpoint',
132+
auth=api.auth,
133+
params={},
134+
json={'arg1': 'value'},
135+
headers={'header1': 'header2'}
136+
)
137+
138+
@patch.object(python_wpapi.requests, 'request')
139+
def test__request_400(mock, api):
140+
mock.return_value.json.return_value = {}
141+
mock.return_value.status_code = 400
142+
with pytest.raises(errors.BadRequestWpApiError) as e:
143+
api._request('endpoint')
144+
assert e.status_code == 400
145+
146+
@patch.object(python_wpapi.requests, 'request')
147+
def test__request_401(mock, api):
148+
mock.return_value.json.return_value = {}
149+
mock.return_value.status_code = 401
150+
with pytest.raises(errors.UnauthorizedWpApiError) as e:
151+
api._request('endpoint2')
152+
assert e.status_code == 401
153+
154+
@patch.object(python_wpapi.requests, 'request')
155+
def test__request_403(mock, api):
156+
mock.return_value.json.return_value = {}
157+
mock.return_value.status_code = 403
158+
with pytest.raises(errors.ForbiddenWpApiError) as e:
159+
api._request('endpoint3')
160+
assert e.status_code == 403
161+
162+
@patch.object(python_wpapi.requests, 'request')
163+
def test__request_404(mock, api):
164+
mock.return_value.json.return_value = {}
165+
mock.return_value.status_code = 404
166+
with pytest.raises(errors.NotFoundWpApiError) as e:
167+
api._request('endpoint4')
168+
assert e.status_code == 404
169+
170+
@patch.object(python_wpapi.requests, 'request')
171+
def test__request_generic(mock, api):
172+
mock.return_value.json.return_value = {}
173+
mock.return_value.status_code = 561
174+
with pytest.raises(errors.WpApiError) as e:
175+
api._request('endpoint4')
176+
assert e.status_code == 561

tox.ini

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[tox]
2+
envlist = py26, py27, py33, py34, py35, flake8
3+
4+
[testenv:flake8]
5+
basepython=python
6+
deps=flake8
7+
commands=flake8 python_wpapi
8+
9+
[testenv]
10+
setenv =
11+
PYTHONPATH = {toxinidir}:{toxinidir}/python_wpapi
12+
deps =
13+
-r{toxinidir}/requirements_dev.txt
14+
commands =
15+
pip install -U pip
16+
py.test --basetemp={envtmpdir}
17+
18+
19+
; If you want to make tox run the tests with the same versions, create a
20+
; requirements.txt with the pinned versions and uncomment the following lines:
21+
; deps =
22+
; -r{toxinidir}/requirements.txt

0 commit comments

Comments
 (0)