Skip to content

Add test for firetactoe. #594

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions appengine/standard/firebase/firetactoe/firetactoe.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def _get_firebase_db_url(_memo={}):
_memo['dburl'] = url.group(1)
return _memo['dburl']


# [START authed_http]
def _get_http(_memo={}):
"""Provides an authed http object."""
Expand All @@ -79,6 +80,7 @@ def _get_http(_memo={}):
return _memo['http']
# [END authed_http]


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


# [START create_token]
def create_custom_token(uid, valid_minutes=60):
"""Create a secure token for the given id.
Expand All @@ -105,17 +108,17 @@ def create_custom_token(uid, valid_minutes=60):
"""

# use the app_identity service from google.appengine.api to get the
# project's service account email automatically
# project's service account email automatically
client_email = app_identity.get_service_account_name()

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


class Game(ndb.Model):
"""All the data we store for a game"""
userX = ndb.UserProperty()
Expand Down Expand Up @@ -193,6 +197,7 @@ def make_move(self, position, user):
return
# [END make_move]


# [START move_route]
@app.route('/move', methods=['POST'])
def move():
Expand All @@ -204,6 +209,7 @@ def move():
return ''
# [END move_route]


# [START route_delete]
@app.route('/delete', methods=['POST'])
def delete():
Expand Down
160 changes: 160 additions & 0 deletions appengine/standard/firebase/firetactoe/firetactoe_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import re

from google.appengine.api import users
from google.appengine.ext import ndb
import httplib2
import pytest
import webtest

import firetactoe


class MockHttp(object):
"""Mock the Http object, so we can set what the response will be."""
def __init__(self, status, content=''):
self.content = content
self.status = status
self.request_url = None

def __call__(self, *args, **kwargs):
return self

def request(self, url, method, content='', *args, **kwargs):
self.request_url = url
self.request_method = method
self.request_content = content
return self, self.content


@pytest.fixture
def app(testbed, monkeypatch, login):
# Don't let the _get_http function memoize its value
orig_get_http = firetactoe._get_http
monkeypatch.setattr(firetactoe, '_get_http', lambda: orig_get_http({}))

# Provide a test firebase config. The following will set the databaseURL
# databaseURL: "http://firebase.com/test-db-url"
monkeypatch.setattr(
firetactoe, '_FIREBASE_CONFIG', '../firetactoe_test.py')

login(id='38')

return webtest.TestApp(firetactoe.app)


def test_index_new_game(app, monkeypatch):
mock_http = MockHttp(200)
monkeypatch.setattr(httplib2, 'Http', mock_http)

response = app.get('/')

assert 'g=' in response.body
# Look for the unique game token
assert re.search(
r'initGame[^\n]+\'[\w+/=]+\.[\w+/=]+\.[\w+/=]+\'', response.body)

assert firetactoe.Game.query().count() == 1

assert mock_http.request_url.startswith(
'http://firebase.com/test-db-url/channels/')
assert mock_http.request_method == 'PATCH'


def test_index_existing_game(app, monkeypatch):
mock_http = MockHttp(200)
monkeypatch.setattr(httplib2, 'Http', mock_http)
userX = users.User('[email protected]', _user_id='123')
firetactoe.Game(id='razem', userX=userX).put()

response = app.get('/?g=razem')

assert 'g=' in response.body
# Look for the unique game token
assert re.search(
r'initGame[^\n]+\'[\w+/=]+\.[\w+/=]+\.[\w+/=]+\'', response.body)

assert firetactoe.Game.query().count() == 1
game = ndb.Key('Game', 'razem').get()
assert game is not None
assert game.userO.user_id() == '38'

assert mock_http.request_url.startswith(
'http://firebase.com/test-db-url/channels/')
assert mock_http.request_method == 'PATCH'


def test_index_nonexisting_game(app, monkeypatch):
mock_http = MockHttp(200)
monkeypatch.setattr(httplib2, 'Http', mock_http)
firetactoe.Game(id='razem', userX=users.get_current_user()).put()

app.get('/?g=razemfrazem', status=404)

assert mock_http.request_url is None


def test_opened(app, monkeypatch):
mock_http = MockHttp(200)
monkeypatch.setattr(httplib2, 'Http', mock_http)
firetactoe.Game(id='razem', userX=users.get_current_user()).put()

app.post('/opened?g=razem', status=200)

assert mock_http.request_url.startswith(
'http://firebase.com/test-db-url/channels/')
assert mock_http.request_method == 'PATCH'


def test_bad_move(app, monkeypatch):
mock_http = MockHttp(200)
monkeypatch.setattr(httplib2, 'Http', mock_http)
firetactoe.Game(
id='razem', userX=users.get_current_user(), board=9*' ',
moveX=True).put()

app.post('/move?g=razem', {'i': 10}, status=400)

assert mock_http.request_url is None


def test_move(app, monkeypatch):
mock_http = MockHttp(200)
monkeypatch.setattr(httplib2, 'Http', mock_http)
firetactoe.Game(
id='razem', userX=users.get_current_user(), board=9*' ',
moveX=True).put()

app.post('/move?g=razem', {'i': 0}, status=200)

game = ndb.Key('Game', 'razem').get()
assert game.board == 'X' + (8 * ' ')

assert mock_http.request_url.startswith(
'http://firebase.com/test-db-url/channels/')
assert mock_http.request_method == 'PATCH'


def test_delete(app, monkeypatch):
mock_http = MockHttp(200)
monkeypatch.setattr(httplib2, 'Http', mock_http)
firetactoe.Game(id='razem', userX=users.get_current_user()).put()

app.post('/delete?g=razem', status=200)

assert mock_http.request_url.startswith(
'http://firebase.com/test-db-url/channels/')
assert mock_http.request_method == 'DELETE'
108 changes: 0 additions & 108 deletions appengine/standard/firebase/firetactoe/rest_api.py

This file was deleted.