10000 Add test for firetactoe. (#594) · docent-net/python-docs-samples@ba53d37 · GitHub
[go: up one dir, main page]

Skip to content

Commit ba53d37

Browse files
authored
Add test for firetactoe. (GoogleCloudPlatform#594)
* Add test for firetactoe. * Fix style errors. * Remove rest_api.py, which may be obsolete. The doc that depends on this is undergoing a rewrite that obviates the need for this file. Plus, checking for "null" seems unnecessary, and there are a bunch of style things that aren't passing our linter.
1 parent 530ab8a commit ba53d37

File tree

3 files changed

+169
-111
lines changed

3 files changed

+169
-111
lines changed

appengine/standard/firebase/firetactoe/firetactoe.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def _get_firebase_db_url(_memo={}):
6464
_memo['dburl'] = url.group(1)
6565
return _memo['dburl']
6666

67+
6768
# [START authed_http]
6869
def _get_http(_memo={}):
6970
"""Provides an authed http object."""
@@ -79,6 +80,7 @@ def _get_http(_memo={}):
7980
return _memo['http']
8081
# [END authed_http]
8182

83+
8284
# [START send_msg]
8385
def _send_firebase_message(u_id, message=None):
8486
"""Updates data in firebase. If a message is provided, then it updates
@@ -94,6 +96,7 @@ def _send_firebase_message(u_id, message=None):
9496
return _get_http().request(url, 'DELETE')
9597
# [END send_msg]
9698

99+
97100
# [START create_token]
98101
def create_custom_token(uid, valid_minutes=60):
99102
"""Create a secure token for the given id.
@@ -105,17 +108,17 @@ def create_custom_token(uid, valid_minutes=60):
105108
"""
106109

107110
# use the app_identity service from google.appengine.api to get the
108-
# project's service account email automatically
111+
# project's service account email automatically
109112
client_email = app_identity.get_service_account_name()
110113

111114
now = int(time.time())
112-
# encode the required claims
115+
# encode the required claims
113116
# per https://firebase.google.com/docs/auth/server/create-custom-tokens
114117
payload = base64.b64encode(json.dumps({
115118
'iss': client_email,
116119
'sub': client_email,
117120
'aud': _IDENTITY_ENDPOINT,
118-
'uid': uid, # this is the important parameter as it will be the channel id
121+
'uid': uid, # the important parameter, as it will be the channel id
119122
'iat': now,
120123
'exp': now + (valid_minutes * 60),
121124
}))
@@ -127,6 +130,7 @@ def create_custom_token(uid, valid_minutes=60):
127130
app_identity.sign_blob(to_sign)[1]))
128131
# [END create_token]
129132

133+
130134
class Game(ndb.Model):
131135
"""All the data we store for a game"""
132136
userX = ndb.UserProperty()
@@ -193,6 +197,7 @@ def make_move(self, position, user):
193197
return
194198
# [END make_move]
195199

200+
196201
# [START move_route]
197202
@app.route('/move', methods=['POST'])
198203
def move():
@@ -204,6 +209,7 @@ def move():
204209
return ''
205210
# [END move_route]
206211

212+
207213
# [START route_delete]
208214
@app.route('/delete', methods=['POST'])
209215
def delete():
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import re
16+
17+
from google.appengine.api import users
18+
from google.appengine.ext import ndb
19+
import httplib2
20+
import pytest
21+
import webtest
22+
23+
import firetactoe
24+
25+
26+
class MockHttp(object):
27+
"""Mock the Http object, so we can set what the response will be."""
28+
def __init__(self, status, content=''):
29+
self.content = content
30+
self.status = status
31+
self.request_url = None
32+
33+
def __call__(self, *args, **kwargs):
34+
return self
35+
36+
def request(self, url, method, content='', *args, **kwargs):
37+
self.request_url = url
38+
self.request_method = method
39+
self.request_content = content
40+
return self, self.content
41+
42+
43+
@pytest.fixture
44+
def app(testbed, monkeypatch, login):
45+
# Don't let the _get_http function memoize its value
46+
orig_get_http = firetactoe._get_http
47+
monkeypatch.setattr(firetactoe, '_get_http', lambda: orig_get_http({}))
48+
49+
# Provide a test firebase config. The following will set the databaseURL
50+
# databaseURL: "http://firebase.com/test-db-url"
51+
monkeypatch.setattr(
52+
firetactoe, '_FIREBASE_CONFIG', '../firetactoe_test.py')
53+
54+
login(id='38')
55+
56+
return webtest.TestApp(firetactoe.app)
57+
58+
59+
def test_index_new_game(app, monkeypatch):
60+
mock_http = MockHttp(200)
61+
monkeypatch.setattr(httplib2, 'Http', mock_http)
62+
63+
response = app.get('/')
64+
65+
assert 'g=' in response.body
66+
# Look for the unique game token
67+
assert re.search(
68+
r'initGame[^\n]+\'[\w+/=]+\.[\w+/=]+\.[\w+/=]+\'', response.body)
69+
70+
assert firetactoe.Game.query().count() == 1
71+
72+
assert mock_http.request_url.startswith(
73+
'http://firebase.com/test-db-url/channels/')
74+
assert mock_http.request_method == 'PATCH'
75+
76+
77+
def test_index_existing_game(app, monkeypatch):
78+
mock_http = MockHttp(200)
79+
monkeypatch.setattr(httplib2, 'Http', mock_http)
80+
userX = users.User('x@example.com', _user_id='123')
81+
firetactoe.Game(id='razem', userX=userX).put()
82+
83+
response = app.get('/?g=razem')
84+
85+
assert 'g=' in response.body
86+
# Look for the unique game token
87+
assert re.search(
88+
r'initGame[^\n]+\'[\w+/=]+\.[\w+/=]+\.[\w+/=]+\'', response.body)
89+
90+
assert firetactoe.Game.query().count() == 1
91+
game = ndb.Key('Game', 'razem').get()
92+
assert game is not None
93+
assert game.userO.user_id() == '38'
94+
95+
assert mock_http.request_url.startswith(
96+
'http://firebase.com/test-db-url/channels/')
97+
assert mock_http.request_method == 'PATCH'
98+
99+
100+
def test_index_nonexisting_game(app, monkeypatch):
101+
mock_http = MockHttp(200)
102+
monkeypatch.setattr(httplib2, 'Http', mock_http)
103+
firetactoe.Game(id='razem', userX=users.get_current_user()).put()
104+
105+
app.get('/?g=razemfrazem', status=404)
106+
107+
assert mock_http.request_url is None
108+
109+
110+
def test_opened(app, monkeypatch):
111+
mock_http = MockHttp(200)
112+
monkeypatch.setattr(httplib2, 'Http', mock_http)
113+
firetactoe.Game(id='razem', userX=users.get_current_user()).put()
114+
115+
app.post('/opened?g=razem', status=200)
116+
117+
assert mock_http.request_url.startswith(
118+
'http://firebase.com/test-db-url/channels/')
119+
assert mock_http.request_method == 'PATCH'
120+
121+
122+
def test_bad_move(app, monkeypatch):
123+
mock_http = MockHttp(200)
124+
monkeypatch.setattr(httplib2, 'Http', mock_http)
125+
firetactoe.Game(
126+
id='razem', userX=users.get_current_user(), board=9*' ',
127+
moveX=True).put()
128+
129+
app.post('/move?g=razem', {'i': 10}, status=400)
130+
131+
assert mock_http.request_url is None
132+
133+
134+
def test_move(app, monkeypatch):
135+
mock_http = MockHttp(200)
136+
monkeypatch.setattr(httplib2, 'Http', mock_http)
137+
firetactoe.Game(
138+
id='razem', userX=users.get_current_user(), board=9*' ',
139+
moveX=True).put()
140+
141+
app.post('/move?g=razem', {'i': 0}, status=200)
142+
143+
game = ndb.Key('Game', 'razem').get()
144+
assert game.board == 'X' + (8 * ' ')
145+
146+
assert mock_http.request_url.startswith(
147+
'http://firebase.com/test-db-url/channels/')
148+
assert mock_http.request_method == 'PATCH'
149+
150+
151+
def test_delete(app, monkeypatch):
152+
mock_http = MockHttp(200)
153+
monkeypatch.setattr(httplib2, 'Http', mock_http)
154+
firetactoe.Game(id='razem', userX=users.get_current_user()).put()
155+
156+
app.post('/delete?g=razem', status=200)
157+
158+
assert mock_http.request_url.startswith(
159+
'http://firebase.com/test-db-url/channels/')
160+
assert mock_http.request_method == 'DELETE'

appengine/standard/firebase/firetactoe/rest_api.py

Lines changed: 0 additions & 108 deletions
This file was deleted.

0 commit comments

Comments
 (0)
0