Show More
@@ -1,96 +1,114 b'' | |||||
1 | """Test the sessions web service API.""" |
|
1 | """Test the sessions web service API.""" | |
2 |
|
2 | |||
3 |
|
3 | import io | ||
4 | import os |
|
4 | import os | |
5 | import sys |
|
|||
6 | import json |
|
5 | import json | |
7 | import requests |
|
6 | import requests | |
|
7 | import shutil | |||
|
8 | ||||
|
9 | pjoin = os.path.join | |||
8 |
|
10 | |||
9 | from IPython.utils.jsonutil import date_default |
|
11 | from IPython.utils.jsonutil import date_default | |
10 | from IPython.html.utils import url_path_join |
|
12 | from IPython.html.utils import url_path_join | |
11 | from IPython.html.tests.launchnotebook import NotebookTestBase |
|
13 | from IPython.html.tests.launchnotebook import NotebookTestBase | |
|
14 | from IPython.nbformat.current import new_notebook, write | |||
|
15 | ||||
|
16 | class SessionAPI(object): | |||
|
17 | """Wrapper for notebook API calls.""" | |||
|
18 | def __init__(self, base_url): | |||
|
19 | self.base_url = base_url | |||
|
20 | ||||
|
21 | def _req(self, verb, path, body=None): | |||
|
22 | response = requests.request(verb, | |||
|
23 | url_path_join(self.base_url, 'api/sessions', path), data=body) | |||
|
24 | ||||
|
25 | if 400 <= response.status_code < 600: | |||
|
26 | try: | |||
|
27 | response.reason = response.json()['message'] | |||
|
28 | except: | |||
|
29 | pass | |||
|
30 | response.raise_for_status() | |||
|
31 | ||||
|
32 | return response | |||
|
33 | ||||
|
34 | def list(self): | |||
|
35 | return self._req('GET', '') | |||
|
36 | ||||
|
37 | def get(self, id): | |||
|
38 | return self._req('GET', id) | |||
|
39 | ||||
|
40 | def create(self, name, path): | |||
|
41 | body = json.dumps({'notebook': {'name':name, 'path':path}}) | |||
|
42 | return self._req('POST', '', body) | |||
|
43 | ||||
|
44 | def modify(self, id, name, path): | |||
|
45 | body = json.dumps({'name':name, 'path':path}) | |||
|
46 | return self._req('PATCH', id, body) | |||
|
47 | ||||
|
48 | def delete(self, id): | |||
|
49 | return self._req('DELETE', id) | |||
12 |
|
50 | |||
13 | class SessionAPITest(NotebookTestBase): |
|
51 | class SessionAPITest(NotebookTestBase): | |
14 | """Test the sessions web service API""" |
|
52 | """Test the sessions web service API""" | |
15 |
|
53 | def setUp(self): | ||
16 | def notebook_url(self): |
|
54 | nbdir = self.notebook_dir.name | |
17 | return url_path_join(super(SessionAPITest,self).base_url(), 'api/notebooks') |
|
55 | os.mkdir(pjoin(nbdir, 'foo')) | |
18 |
|
56 | |||
19 | def session_url(self): |
|
57 | with io.open(pjoin(nbdir, 'foo', 'nb1.ipynb'), 'w') as f: | |
20 | return super(SessionAPITest,self).base_url() + 'api/sessions' |
|
58 | nb = new_notebook(name='nb1') | |
21 |
|
59 | write(nb, f, format='ipynb') | ||
22 | def mknb(self, name='', path='/'): |
|
60 | ||
23 | url = self.notebook_url() + path |
|
61 | self.sess_api = SessionAPI(self.base_url()) | |
24 | return url, requests.post(url) |
|
62 | ||
25 |
|
63 | def tearDown(self): | ||
26 | def delnb(self, name, path='/'): |
|
64 | for session in self.sess_api.list().json(): | |
27 | url = self.notebook_url() + path + name |
|
65 | self.sess_api.delete(session['id']) | |
28 | r = requests.delete(url) |
|
66 | shutil.rmtree(pjoin(self.notebook_dir.name, 'foo')) | |
29 | return r.status_code |
|
67 | ||
30 |
|
68 | def assert_404(self, id): | ||
31 | def test_no_sessions(self): |
|
69 | try: | |
32 | """Make sure there are no sessions running at the start""" |
|
70 | self.sess_api.get(id) | |
33 | url = self.session_url() |
|
71 | except requests.HTTPError as e: | |
34 | r = requests.get(url) |
|
72 | self.assertEqual(e.response.status_code, 404) | |
35 | self.assertEqual(r.json(), []) |
|
73 | else: | |
36 |
|
74 | assert False, "Getting nonexistent session didn't give HTTP error" | ||
37 | def test_session_root_handler(self): |
|
75 | ||
38 | # POST a session |
|
76 | def test_create(self): | |
39 | url, nb = self.mknb() |
|
77 | sessions = self.sess_api.list().json() | |
40 | notebook = nb.json() |
|
78 | self.assertEqual(len(sessions), 0) | |
41 | model = {'notebook': {'name':notebook['name'], 'path': notebook['path']}} |
|
79 | ||
42 | r = requests.post(self.session_url(), data=json.dumps(model, default=date_default)) |
|
80 | resp = self.sess_api.create('nb1.ipynb', 'foo') | |
43 | data = r.json() |
|
81 | self.assertEqual(resp.status_code, 201) | |
44 | assert isinstance(data, dict) |
|
82 | newsession = resp.json() | |
45 |
self.assertIn(' |
|
83 | self.assertIn('id', newsession) | |
46 |
self.assertEqual( |
|
84 | self.assertEqual(newsession['notebook']['name'], 'nb1.ipynb') | |
47 |
|
85 | self.assertEqual(newsession['notebook']['path'], 'foo') | ||
48 | # GET sessions |
|
86 | ||
49 | r = requests.get(self.session_url()) |
|
87 | sessions = self.sess_api.list().json() | |
50 | assert isinstance(r.json(), list) |
|
88 | self.assertEqual(sessions, [newsession]) | |
51 | assert isinstance(r.json()[0], dict) |
|
89 | ||
52 | self.assertEqual(r.json()[0]['id'], data['id']) |
|
90 | # Retrieve it | |
53 |
|
91 | sid = newsession['id'] | ||
54 | # Clean up |
|
92 | got = self.sess_api.get(sid) | |
55 | self.delnb('Untitled0.ipynb') |
|
93 | self.assertEqual(got, newsession) | |
56 | sess_url = self.session_url() +'/'+data['id'] |
|
94 | ||
57 |
|
|
95 | def test_delete(self): | |
58 | self.assertEqual(r.status_code, 204) |
|
96 | newsession = self.sess_api.create('nb1.ipynb', 'foo').json() | |
59 |
|
97 | sid = newsession['id'] | ||
60 | def test_session_handler(self): |
|
98 | ||
61 | # Create a session |
|
99 | resp = self.sess_api.delete(sid) | |
62 | url, nb = self.mknb() |
|
100 | self.assertEqual(resp.status_code, 204) | |
63 | notebook = nb.json() |
|
101 | ||
64 | model = {'notebook': {'name':notebook['name'], 'path': notebook['path']}} |
|
102 | sessions = self.sess_api.list().json() | |
65 | r = requests.post(self.session_url(), data=json.dumps(model, default=date_default)) |
|
103 | self.assertEqual(sessions, []) | |
66 | session = r.json() |
|
104 | ||
67 |
|
105 | self.assert_404(sid) | ||
68 | # GET a session |
|
106 | ||
69 | sess_url = self.session_url() + '/' + session['id'] |
|
107 | def test_modify(self): | |
70 | r = requests.get(sess_url) |
|
108 | newsession = self.sess_api.create('nb1.ipynb', 'foo').json() | |
71 | assert isinstance(r.json(), dict) |
|
109 | sid = newsession['id'] | |
72 | self.assertEqual(r.json(), session) |
|
110 | ||
73 |
|
111 | changed = self.sess_api.modify(sid, 'nb2.ipynb', '').json() | ||
74 | # PATCH a session |
|
112 | self.assertEqual(changed['id'], sid) | |
75 | model = {'notebook': {'name':'test.ipynb', 'path': '/'}} |
|
113 | self.assertEqual(newsession['notebook']['name'], 'nb2.ipynb') | |
76 | r = requests.patch(sess_url, data=json.dumps(model, default=date_default)) |
|
114 | self.assertEqual(newsession['notebook']['path'], '') | |
77 |
|
||||
78 | # Patching the notebook webservice too (just for consistency) |
|
|||
79 | requests.patch(self.notebook_url() + '/Untitled0.ipynb', |
|
|||
80 | data=json.dumps({'name':'test.ipynb'})) |
|
|||
81 | print r.json() |
|
|||
82 | assert isinstance(r.json(), dict) |
|
|||
83 | self.assertIn('name', r.json()['notebook']) |
|
|||
84 | self.assertIn('id', r.json()) |
|
|||
85 | self.assertEqual(r.json()['notebook']['name'], 'test.ipynb') |
|
|||
86 | self.assertEqual(r.json()['id'], session['id']) |
|
|||
87 |
|
||||
88 | # DELETE a session |
|
|||
89 | r = requests.delete(sess_url) |
|
|||
90 | self.assertEqual(r.status_code, 204) |
|
|||
91 | r = requests.get(self.session_url()) |
|
|||
92 | self.assertEqual(r.json(), []) |
|
|||
93 |
|
||||
94 | # Clean up |
|
|||
95 | r = self.delnb('test.ipynb') |
|
|||
96 | self.assertEqual(r, 204) No newline at end of file |
|
General Comments 0
You need to be logged in to leave comments.
Login now