Move routing configuration to main.py. (#1552)
* Move routing configuration to main.py. * inline_file works so we dont need this directive * rebased * Removed __future__s
This commit is contained in:
Родитель
84e42f798a
Коммит
527c49abed
|
@ -23,9 +23,10 @@ import mock
|
|||
import werkzeug.exceptions # Flask HTTP stuff.
|
||||
|
||||
from api import accounts_api
|
||||
from api import register
|
||||
from internals import models
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class AccountsAPITest(testing_config.CustomTestCase):
|
||||
|
||||
|
@ -49,7 +50,7 @@ class AccountsAPITest(testing_config.CustomTestCase):
|
|||
testing_config.sign_in('admin@example.com', 123567890)
|
||||
|
||||
json_data = {'email': 'new@example.com', 'isAdmin': False}
|
||||
with register.app.test_request_context(self.request_path, json=json_data):
|
||||
with test_app.test_request_context(self.request_path, json=json_data):
|
||||
actual_json = self.handler.do_post()
|
||||
self.assertEqual('new@example.com', actual_json['email'])
|
||||
self.assertFalse(actual_json['is_admin'])
|
||||
|
@ -64,7 +65,7 @@ class AccountsAPITest(testing_config.CustomTestCase):
|
|||
testing_config.sign_in('admin@example.com', 123567890)
|
||||
|
||||
json_data = {'email': 'new_admin@example.com', 'isAdmin': True}
|
||||
with register.app.test_request_context(self.request_path, json=json_data):
|
||||
with test_app.test_request_context(self.request_path, json=json_data):
|
||||
actual_json = self.handler.do_post()
|
||||
self.assertEqual('new_admin@example.com', actual_json['email'])
|
||||
self.assertTrue(actual_json['is_admin'])
|
||||
|
@ -78,7 +79,7 @@ class AccountsAPITest(testing_config.CustomTestCase):
|
|||
"""Regular user cannot create an account."""
|
||||
testing_config.sign_in('one@example.com', 123567890)
|
||||
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.do_post(self.appuser_id)
|
||||
|
||||
|
@ -91,7 +92,7 @@ class AccountsAPITest(testing_config.CustomTestCase):
|
|||
testing_config.sign_in('admin@example.com', 123567890)
|
||||
|
||||
json_data = {'isAdmin': False} # No email
|
||||
with register.app.test_request_context(self.request_path, json=json_data):
|
||||
with test_app.test_request_context(self.request_path, json=json_data):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
|
@ -104,7 +105,7 @@ class AccountsAPITest(testing_config.CustomTestCase):
|
|||
testing_config.sign_in('admin@example.com', 123567890)
|
||||
|
||||
json_data = {'email': 'user@example.com'}
|
||||
with register.app.test_request_context(self.request_path, json=json_data):
|
||||
with test_app.test_request_context(self.request_path, json=json_data):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
|
@ -115,7 +116,7 @@ class AccountsAPITest(testing_config.CustomTestCase):
|
|||
"""Admin wants to delete an account."""
|
||||
testing_config.sign_in('admin@example.com', 123567890)
|
||||
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_json = self.handler.do_delete(self.appuser_id)
|
||||
self.assertEqual({'message': 'Done'}, actual_json)
|
||||
|
||||
|
@ -126,7 +127,7 @@ class AccountsAPITest(testing_config.CustomTestCase):
|
|||
"""Regular user cannot delete an account."""
|
||||
testing_config.sign_in('one@example.com', 123567890)
|
||||
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.do_delete(self.appuser_id)
|
||||
|
||||
|
@ -137,7 +138,7 @@ class AccountsAPITest(testing_config.CustomTestCase):
|
|||
"""We cannot delete an account without an account_id."""
|
||||
testing_config.sign_in('admin@example.com', 123567890)
|
||||
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_delete(None)
|
||||
|
||||
|
@ -149,7 +150,7 @@ class AccountsAPITest(testing_config.CustomTestCase):
|
|||
"""We cannot delete an account with the wrong account_id."""
|
||||
testing_config.sign_in('admin@example.com', 123567890)
|
||||
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.NotFound):
|
||||
self.handler.do_delete(self.appuser_id + 1)
|
||||
|
||||
|
|
|
@ -22,10 +22,10 @@ import flask
|
|||
import mock
|
||||
import werkzeug.exceptions # Flask HTTP stuff.
|
||||
|
||||
from api import register
|
||||
from api import approvals_api
|
||||
from internals import models
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
NOW = datetime.datetime.now()
|
||||
|
||||
|
@ -74,7 +74,7 @@ class ApprovalsAPITest(testing_config.CustomTestCase):
|
|||
def test_get__all_empty(self):
|
||||
"""We can get all approvals for a given feature, even if there none."""
|
||||
testing_config.sign_out()
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.do_get(self.feature_id)
|
||||
self.assertEqual({"approvals": []}, actual_response)
|
||||
|
||||
|
@ -84,7 +84,7 @@ class ApprovalsAPITest(testing_config.CustomTestCase):
|
|||
self.appr_1_1.put()
|
||||
self.appr_1_2.put()
|
||||
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.do_get(self.feature_id)
|
||||
|
||||
self.assertEqual(
|
||||
|
@ -94,7 +94,7 @@ class ApprovalsAPITest(testing_config.CustomTestCase):
|
|||
def test_get__field_empty(self):
|
||||
"""We can get approvals for given feature and field, even if there none."""
|
||||
testing_config.sign_out()
|
||||
with register.app.test_request_context(self.request_path + '/1'):
|
||||
with test_app.test_request_context(self.request_path + '/1'):
|
||||
actual_response = self.handler.do_get(self.feature_id, field_id=1)
|
||||
self.assertEqual({"approvals": []}, actual_response)
|
||||
|
||||
|
@ -104,7 +104,7 @@ class ApprovalsAPITest(testing_config.CustomTestCase):
|
|||
self.appr_1_1.put()
|
||||
self.appr_1_2.put()
|
||||
|
||||
with register.app.test_request_context(self.request_path + '/1'):
|
||||
with test_app.test_request_context(self.request_path + '/1'):
|
||||
actual_response = self.handler.do_get(self.feature_id, field_id=1)
|
||||
|
||||
self.assertEqual(
|
||||
|
@ -114,48 +114,48 @@ class ApprovalsAPITest(testing_config.CustomTestCase):
|
|||
def test_post__bad_feature_id(self):
|
||||
"""Handler rejects requests that don't specify a feature ID correctly."""
|
||||
params = {}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
params = {'featureId': 'not an int'}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
def test_post__bad_field_id(self):
|
||||
"""Handler rejects requests that don't specify a field ID correctly."""
|
||||
params = {'featureId': self.feature_id}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
params = {'featureId': self.feature_id, 'fieldId': 'not an int'}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
params = {'featureId': self.feature_id, 'fieldId': 999}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
def test_post__bad_state(self):
|
||||
"""Handler rejects requests that don't specify a state correctly."""
|
||||
params = {'featureId': self.feature_id, 'fieldId': 1}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
params = {'featureId': self.feature_id, 'fieldId': 1,
|
||||
'state': 'not an int'}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
params = {'featureId': self.feature_id, 'fieldId': 1,
|
||||
'state': 999}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
|
@ -163,7 +163,7 @@ class ApprovalsAPITest(testing_config.CustomTestCase):
|
|||
"""Handler rejects requests that don't match an existing feature."""
|
||||
params = {'featureId': 12345, 'fieldId': 1,
|
||||
'state': models.Approval.NEED_INFO }
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.NotFound):
|
||||
self.handler.do_post()
|
||||
|
||||
|
@ -175,17 +175,17 @@ class ApprovalsAPITest(testing_config.CustomTestCase):
|
|||
'state': models.Approval.NEED_INFO}
|
||||
|
||||
testing_config.sign_out()
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.do_post()
|
||||
|
||||
testing_config.sign_in('user7@example.com', 123567890)
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.do_post()
|
||||
|
||||
testing_config.sign_in('user@google.com', 123567890)
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.do_post()
|
||||
|
||||
|
@ -196,7 +196,7 @@ class ApprovalsAPITest(testing_config.CustomTestCase):
|
|||
testing_config.sign_in('owner1@example.com', 123567890)
|
||||
params = {'featureId': self.feature_id, 'fieldId': 1,
|
||||
'state': models.Approval.NEED_INFO}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
actual = self.handler.do_post()
|
||||
|
||||
self.assertEqual(actual, {'message': 'Done'})
|
||||
|
@ -206,4 +206,4 @@ class ApprovalsAPITest(testing_config.CustomTestCase):
|
|||
self.assertEqual(appr.feature_id, self.feature_id)
|
||||
self.assertEqual(appr.field_id, 1)
|
||||
self.assertEqual(appr.set_by, 'owner1@example.com')
|
||||
self.assertEqual(appr.state, models.Approval.NEED_INFO)
|
||||
self.assertEqual(appr.state, models.Approval.NEED_INFO)
|
||||
|
|
|
@ -23,10 +23,10 @@ import flask
|
|||
import mock
|
||||
import werkzeug.exceptions # Flask HTTP stuff.
|
||||
|
||||
from api import register
|
||||
from api import comments_api
|
||||
from internals import models
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
NOW = datetime.datetime.now()
|
||||
|
||||
|
@ -77,7 +77,7 @@ class CommentsAPITest(testing_config.CustomTestCase):
|
|||
def test_get__empty(self):
|
||||
"""We can get comments for a given approval, even if there none."""
|
||||
testing_config.sign_out()
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.do_get(self.feature_id, self.field_id)
|
||||
self.assertEqual({'comments': []}, actual_response)
|
||||
|
||||
|
@ -86,7 +86,7 @@ class CommentsAPITest(testing_config.CustomTestCase):
|
|||
testing_config.sign_out()
|
||||
self.cmnt_1_1.put()
|
||||
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.do_get(self.feature_id, self.field_id)
|
||||
|
||||
actual_comment = actual_response['comments'][0]
|
||||
|
@ -98,12 +98,12 @@ class CommentsAPITest(testing_config.CustomTestCase):
|
|||
def test_post__bad_state(self):
|
||||
"""Handler rejects requests that don't specify a state correctly."""
|
||||
params = {'state': 'not an int'}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post(self.feature_id, self.field_id)
|
||||
|
||||
params = {'state': 999}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post(self.feature_id, self.field_id)
|
||||
|
||||
|
@ -111,7 +111,7 @@ class CommentsAPITest(testing_config.CustomTestCase):
|
|||
"""Handler rejects requests that don't match an existing feature."""
|
||||
bad_path = '/api/v0/features/12345/approvals/1/comments'
|
||||
params = {'state': models.Approval.NEED_INFO }
|
||||
with register.app.test_request_context(bad_path, json=params):
|
||||
with test_app.test_request_context(bad_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.NotFound):
|
||||
self.handler.do_post(12345, self.field_id)
|
||||
|
||||
|
@ -122,17 +122,17 @@ class CommentsAPITest(testing_config.CustomTestCase):
|
|||
params = {'state': models.Approval.NEED_INFO}
|
||||
|
||||
testing_config.sign_out()
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.do_post(self.feature_id, self.field_id)
|
||||
|
||||
testing_config.sign_in('user7@example.com', 123567890)
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.do_post(self.feature_id, self.field_id)
|
||||
|
||||
testing_config.sign_in('user@google.com', 123567890)
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.do_post(self.feature_id, self.field_id)
|
||||
|
||||
|
@ -142,7 +142,7 @@ class CommentsAPITest(testing_config.CustomTestCase):
|
|||
mock_get_approvers.return_value = ['owner1@example.com']
|
||||
testing_config.sign_in('owner1@example.com', 123567890)
|
||||
params = {'state': models.Approval.NEED_INFO}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
actual = self.handler.do_post(self.feature_id, self.field_id)
|
||||
|
||||
self.assertEqual(actual, {'message': 'Done'})
|
||||
|
@ -166,7 +166,7 @@ class CommentsAPITest(testing_config.CustomTestCase):
|
|||
mock_get_approvers.return_value = []
|
||||
testing_config.sign_in('owner2@example.com', 123567890)
|
||||
params = {'comment': 'Congratulations'}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
actual = self.handler.do_post(self.feature_id, self.field_id)
|
||||
|
||||
self.assertEqual(actual, {'message': 'Done'})
|
||||
|
@ -182,4 +182,4 @@ class CommentsAPITest(testing_config.CustomTestCase):
|
|||
cmnt = updated_comments[0]
|
||||
self.assertEqual('Congratulations', cmnt.content)
|
||||
self.assertIsNone(cmnt.old_approval_state)
|
||||
self.assertIsNone(cmnt.new_approval_state)
|
||||
self.assertIsNone(cmnt.new_approval_state)
|
||||
|
|
|
@ -22,9 +22,10 @@ import mock
|
|||
import werkzeug.exceptions # Flask HTTP stuff.
|
||||
|
||||
from api import cues_api
|
||||
from api import register
|
||||
from internals import models
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class CuesAPITest(testing_config.CustomTestCase):
|
||||
|
||||
|
@ -42,7 +43,7 @@ class CuesAPITest(testing_config.CustomTestCase):
|
|||
"""User wants to dismiss a valid cue card ID."""
|
||||
testing_config.sign_in('one@example.com', 123567890)
|
||||
|
||||
with register.app.test_request_context(
|
||||
with test_app.test_request_context(
|
||||
'/cues/dismiss', json={"cue": "progress-checkmarks"}):
|
||||
actual_json = self.handler.do_post()
|
||||
self.assertEqual({'message': 'Done'}, actual_json)
|
||||
|
@ -54,11 +55,11 @@ class CuesAPITest(testing_config.CustomTestCase):
|
|||
"""User wants to dismiss an invalid cue card ID."""
|
||||
testing_config.sign_in('one@example.com', 123567890)
|
||||
|
||||
with register.app.test_request_context(
|
||||
with test_app.test_request_context(
|
||||
'/cues/dismiss', json={"cue": "xyz"}):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
# The invalid string should not be added.
|
||||
revised_user_pref = models.UserPref.get_signed_in_user_pref()
|
||||
self.assertEqual([], revised_user_pref.dismissed_cues)
|
||||
self.assertEqual([], revised_user_pref.dismissed_cues)
|
||||
|
|
|
@ -22,10 +22,11 @@ import mock
|
|||
import werkzeug.exceptions # Flask HTTP stuff.
|
||||
|
||||
from api import features_api
|
||||
from api import register
|
||||
from internals import models
|
||||
from framework import ramcache
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class FeaturesAPITestDelete(testing_config.CustomTestCase):
|
||||
|
||||
|
@ -55,7 +56,7 @@ class FeaturesAPITestDelete(testing_config.CustomTestCase):
|
|||
"""Admin wants to soft-delete a feature."""
|
||||
testing_config.sign_in('admin@example.com', 123567890)
|
||||
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_json = self.handler.do_delete(self.feature_id)
|
||||
self.assertEqual({'message': 'Done'}, actual_json)
|
||||
|
||||
|
@ -66,7 +67,7 @@ class FeaturesAPITestDelete(testing_config.CustomTestCase):
|
|||
"""Regular user cannot soft-delete a feature."""
|
||||
testing_config.sign_in('one@example.com', 123567890)
|
||||
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.do_delete(self.feature_id)
|
||||
|
||||
|
@ -77,7 +78,7 @@ class FeaturesAPITestDelete(testing_config.CustomTestCase):
|
|||
"""We cannot soft-delete a feature without a feature_id."""
|
||||
testing_config.sign_in('admin@example.com', 123567890)
|
||||
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_delete(None)
|
||||
|
||||
|
@ -88,7 +89,7 @@ class FeaturesAPITestDelete(testing_config.CustomTestCase):
|
|||
"""We cannot soft-delete a feature with the wrong feature_id."""
|
||||
testing_config.sign_in('admin@example.com', 123567890)
|
||||
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.NotFound):
|
||||
self.handler.do_delete(self.feature_id + 1)
|
||||
|
||||
|
@ -122,7 +123,7 @@ class FeaturesAPITestGet(testing_config.CustomTestCase):
|
|||
|
||||
def test_get__all_listed(self):
|
||||
"""Get all features that are listed."""
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.do_get()
|
||||
|
||||
# Comparing only the total number of features and name of the feature
|
||||
|
@ -136,13 +137,13 @@ class FeaturesAPITestGet(testing_config.CustomTestCase):
|
|||
self.feature_1.put()
|
||||
|
||||
# No signed-in user
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.do_get()
|
||||
self.assertEqual(0, len(actual_response))
|
||||
|
||||
# Signed-in user with no permissions
|
||||
testing_config.sign_in('one@example.com', 123567890)
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.do_get()
|
||||
self.assertEqual(0, len(actual_response))
|
||||
|
||||
|
@ -153,7 +154,7 @@ class FeaturesAPITestGet(testing_config.CustomTestCase):
|
|||
|
||||
# Signed-in user with permissions
|
||||
testing_config.sign_in('admin@example.com', 123567890)
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.do_get()
|
||||
self.assertEqual(1, len(actual_response))
|
||||
self.assertEqual('feature one', actual_response[0]['name'])
|
||||
|
@ -161,13 +162,13 @@ class FeaturesAPITestGet(testing_config.CustomTestCase):
|
|||
def test_get__in_milestone_listed(self):
|
||||
"""Get all features in a specific milestone that are listed."""
|
||||
# Atleast one feature is present in milestone
|
||||
with register.app.test_request_context(self.request_path+'?milestone=1'):
|
||||
with test_app.test_request_context(self.request_path+'?milestone=1'):
|
||||
actual_response = self.handler.do_get()
|
||||
self.assertEqual(6, len(actual_response))
|
||||
self.assertEqual(1, len(actual_response['Enabled by default']))
|
||||
|
||||
# No Feature is present in milestone
|
||||
with register.app.test_request_context(self.request_path+'?milestone=2'):
|
||||
with test_app.test_request_context(self.request_path+'?milestone=2'):
|
||||
actual_response = self.handler.do_get()
|
||||
self.assertEqual(6, len(actual_response))
|
||||
self.assertEqual(0, len(actual_response['Enabled by default']))
|
||||
|
@ -178,14 +179,14 @@ class FeaturesAPITestGet(testing_config.CustomTestCase):
|
|||
self.feature_1.put()
|
||||
|
||||
# No signed-in user
|
||||
with register.app.test_request_context(self.request_path+'?milestone=1'):
|
||||
with test_app.test_request_context(self.request_path+'?milestone=1'):
|
||||
actual_response = self.handler.do_get()
|
||||
self.assertEqual(6, len(actual_response))
|
||||
self.assertEqual(0, len(actual_response['Enabled by default']))
|
||||
|
||||
# Signed-in user with no permissions
|
||||
testing_config.sign_in('one@example.com', 123567890)
|
||||
with register.app.test_request_context(self.request_path+'?milestone=1'):
|
||||
with test_app.test_request_context(self.request_path+'?milestone=1'):
|
||||
actual_response = self.handler.do_get()
|
||||
self.assertEqual(6, len(actual_response))
|
||||
self.assertEqual(0, len(actual_response['Enabled by default']))
|
||||
|
@ -199,13 +200,13 @@ class FeaturesAPITestGet(testing_config.CustomTestCase):
|
|||
testing_config.sign_in('admin@example.com', 123567890)
|
||||
|
||||
# Feature is present in milestone
|
||||
with register.app.test_request_context(self.request_path+'?milestone=1'):
|
||||
with test_app.test_request_context(self.request_path+'?milestone=1'):
|
||||
actual_response = self.handler.do_get()
|
||||
self.assertEqual(6, len(actual_response))
|
||||
self.assertEqual(1, len(actual_response['Enabled by default']))
|
||||
|
||||
# Feature is not present in milestone
|
||||
with register.app.test_request_context(self.request_path+'?milestone=2'):
|
||||
with test_app.test_request_context(self.request_path+'?milestone=2'):
|
||||
actual_response = self.handler.do_get()
|
||||
self.assertEqual(6, len(actual_response))
|
||||
self.assertEqual(0, len(actual_response['Enabled by default']))
|
||||
|
@ -215,7 +216,7 @@ class FeaturesAPITestGet(testing_config.CustomTestCase):
|
|||
"""Invalid value of milestone should not be processed."""
|
||||
|
||||
# Feature is present in milestone
|
||||
with register.app.test_request_context(
|
||||
self.request_path + '?milestone=chromium'):
|
||||
with test_app.test_request_context(
|
||||
self.request_path+'?milestone=chromium'):
|
||||
actual_response = self.handler.do_get()
|
||||
mock_abort.assert_called_once_with(400, description='Invalid Milestone')
|
||||
|
|
|
@ -28,12 +28,10 @@ from framework import users
|
|||
from framework import basehandlers
|
||||
from internals import models
|
||||
from framework import ramcache
|
||||
import settings
|
||||
|
||||
CACHE_AGE = 86400 # 24hrs
|
||||
|
||||
|
||||
|
||||
def _truncate_day_percentage(datapoint):
|
||||
# Need 8 decimals b/c num will by multiplied by 100 to get a percentage and
|
||||
# we want 6 decimals.
|
||||
|
@ -247,14 +245,3 @@ class FeatureBucketsHandler(basehandlers.FlaskHandler):
|
|||
models.FeatureObserverHistogram.get_all().items(), key=lambda x:x[1])
|
||||
|
||||
return properties
|
||||
|
||||
|
||||
app = basehandlers.FlaskApplication([
|
||||
('/data/timeline/cssanimated', AnimatedTimelineHandler),
|
||||
('/data/timeline/csspopularity', PopularityTimelineHandler),
|
||||
('/data/timeline/featurepopularity', FeatureObserverTimelineHandler),
|
||||
('/data/csspopularity', CSSPopularityHandler),
|
||||
('/data/cssanimated', CSSAnimatedHandler),
|
||||
('/data/featurepopularity', FeatureObserverPopularityHandler),
|
||||
('/data/blink/<string:prop_type>', FeatureBucketsHandler),
|
||||
], debug=settings.DEBUG)
|
||||
|
|
|
@ -27,6 +27,8 @@ from framework import users
|
|||
from api import metricsdata
|
||||
from internals import models
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class MetricsFunctionTests(testing_config.CustomTestCase):
|
||||
|
||||
|
@ -85,14 +87,14 @@ class PopularityTimelineHandlerTests(testing_config.CustomTestCase):
|
|||
|
||||
def test_get_template_data__bad_bucket(self):
|
||||
url = '/data/timeline/csspopularity?bucket_id=not-a-number'
|
||||
with metricsdata.app.test_request_context(url):
|
||||
with test_app.test_request_context(url):
|
||||
actual = self.handler.get_template_data()
|
||||
self.assertEqual([], actual)
|
||||
|
||||
def test_get_template_data__normal(self):
|
||||
testing_config.sign_out()
|
||||
url = '/data/timeline/csspopularity?bucket_id=1'
|
||||
with metricsdata.app.test_request_context(url):
|
||||
with test_app.test_request_context(url):
|
||||
actual_datapoints = self.handler.get_template_data()
|
||||
self.assertEqual(1, len(actual_datapoints))
|
||||
self.assertEqual(0.01234568, actual_datapoints[0]['day_percentage'])
|
||||
|
@ -125,15 +127,15 @@ class FeatureBucketsHandlerTest(testing_config.CustomTestCase):
|
|||
self.prop_4.key.delete()
|
||||
|
||||
def test_get_template_data__css(self):
|
||||
with metricsdata.app.test_request_context('/data/blink/cssprops'):
|
||||
with test_app.test_request_context('/data/blink/cssprops'):
|
||||
actual_buckets = self.handler.get_template_data('cssprops')
|
||||
self.assertEqual(
|
||||
[(2, 'a prop'), (1, 'b prop')],
|
||||
actual_buckets)
|
||||
|
||||
def test_get_template_data__js(self):
|
||||
with metricsdata.app.test_request_context('/data/blink/features'):
|
||||
with test_app.test_request_context('/data/blink/features'):
|
||||
actual_buckets = self.handler.get_template_data('features')
|
||||
self.assertEqual(
|
||||
[(4, 'a feat'), (3, 'b feat')],
|
||||
actual_buckets)
|
||||
actual_buckets)
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2021 Google Inc.
|
||||
#
|
||||
# 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 settings
|
||||
from api import accounts_api
|
||||
from api import approvals_api
|
||||
from api import comments_api
|
||||
from api import cues_api
|
||||
from api import features_api
|
||||
from api import stars_api
|
||||
from api import token_refresh_api
|
||||
from api import channels_api
|
||||
from framework import basehandlers
|
||||
|
||||
from api import login_api
|
||||
from api import logout_api
|
||||
|
||||
|
||||
# TODO(jrobbins): Advance this to v1 once we have it fleshed out
|
||||
API_BASE = '/api/v0'
|
||||
|
||||
app = basehandlers.FlaskApplication([
|
||||
('/features', features_api.FeaturesAPI),
|
||||
('/features/<int:feature_id>', features_api.FeaturesAPI),
|
||||
('/features/<int:feature_id>/approvals/<int:field_id>',
|
||||
approvals_api.ApprovalsAPI),
|
||||
('/features/<int:feature_id>/approvals/<int:field_id>/comments',
|
||||
comments_api.CommentsAPI),
|
||||
|
||||
('/login', login_api.LoginAPI),
|
||||
('/logout', logout_api.LogoutAPI),
|
||||
('/currentuser/stars', stars_api.StarsAPI),
|
||||
('/currentuser/cues', cues_api.CuesAPI),
|
||||
('/currentuser/token', token_refresh_api.TokenRefreshAPI),
|
||||
# ('/currentuser/autosaves', TODO),
|
||||
# ('/currentuser/settings', TODO),
|
||||
|
||||
# Admin operations for user accounts
|
||||
('/accounts', accounts_api.AccountsAPI),
|
||||
('/accounts/<int:account_id>', accounts_api.AccountsAPI),
|
||||
|
||||
('/channels', channels_api.ChannelsAPI), # omaha data
|
||||
# ('/schedule', TODO), # chromiumdash data
|
||||
# ('/metrics/<str:kind>', TODO), # uma-export data
|
||||
# ('/metrics/<str:kind>/<int:bucket_id>', TODO),
|
||||
|
||||
],
|
||||
pattern_base=API_BASE,
|
||||
debug=settings.DEBUG)
|
|
@ -21,11 +21,11 @@ import flask
|
|||
import mock
|
||||
import werkzeug.exceptions # Flask HTTP stuff.
|
||||
|
||||
from api import register
|
||||
from api import stars_api
|
||||
from internals import models
|
||||
from internals import notifier
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class StarsAPITest(testing_config.CustomTestCase):
|
||||
|
@ -46,14 +46,14 @@ class StarsAPITest(testing_config.CustomTestCase):
|
|||
def test_get__anon(self):
|
||||
"""Anon should always have an empty list of stars."""
|
||||
testing_config.sign_out()
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.do_get()
|
||||
self.assertEqual({"featureIds": []}, actual_response)
|
||||
|
||||
def test_get__no_stars(self):
|
||||
"""User has not starred any features."""
|
||||
testing_config.sign_in('user7@example.com', 123567890)
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.do_get()
|
||||
self.assertEqual({"featureIds": []}, actual_response)
|
||||
|
||||
|
@ -63,7 +63,7 @@ class StarsAPITest(testing_config.CustomTestCase):
|
|||
feature_1_id = self.feature_1.key.integer_id()
|
||||
testing_config.sign_in(email, 123567890)
|
||||
notifier.FeatureStar.set_star(email, feature_1_id)
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.do_get()
|
||||
self.assertEqual(
|
||||
{"featureIds": [feature_1_id]},
|
||||
|
@ -72,19 +72,19 @@ class StarsAPITest(testing_config.CustomTestCase):
|
|||
def test_post__invalid_feature_id(self):
|
||||
"""We reject star requests that don't have an int featureId."""
|
||||
params = {}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
params = {"featureId": "not an int"}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.do_post()
|
||||
|
||||
def test_post__feature_id_not_found(self):
|
||||
"""We reject star requests for features that don't exist."""
|
||||
params = {"featureId": 999}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.NotFound):
|
||||
self.handler.do_post()
|
||||
|
||||
|
@ -93,7 +93,7 @@ class StarsAPITest(testing_config.CustomTestCase):
|
|||
feature_id = self.feature_1.key.integer_id()
|
||||
params = {"featureId": feature_id}
|
||||
testing_config.sign_out()
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.do_post()
|
||||
|
||||
|
@ -103,24 +103,24 @@ class StarsAPITest(testing_config.CustomTestCase):
|
|||
|
||||
feature_id = self.feature_1.key.integer_id()
|
||||
params = {"featureId": feature_id}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
self.handler.do_post() # Original request
|
||||
|
||||
updated_feature = models.Feature.get_by_id(feature_id)
|
||||
self.assertEqual(1, updated_feature.star_count)
|
||||
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
self.handler.do_post() # Duplicate request
|
||||
updated_feature = models.Feature.get_by_id(feature_id)
|
||||
self.assertEqual(1, updated_feature.star_count) # Still 1, not 2.
|
||||
|
||||
params = {"featureId": feature_id, "starred": False}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
self.handler.do_post() # Original request
|
||||
updated_feature = models.Feature.get_by_id(feature_id)
|
||||
self.assertEqual(0, updated_feature.star_count)
|
||||
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
self.handler.do_post() # Duplicate request
|
||||
updated_feature = models.Feature.get_by_id(feature_id)
|
||||
self.assertEqual(0, updated_feature.star_count) # Still 0, not negative.
|
||||
|
@ -133,7 +133,7 @@ class StarsAPITest(testing_config.CustomTestCase):
|
|||
# User never stars the feature in the first place.
|
||||
|
||||
params = {"featureId": feature_id, "starred": False}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
self.handler.do_post() # Out-of-step request
|
||||
updated_feature = models.Feature.get_by_id(feature_id)
|
||||
self.assertEqual(0, updated_feature.star_count) # Still 0, not negative.
|
||||
|
@ -144,13 +144,13 @@ class StarsAPITest(testing_config.CustomTestCase):
|
|||
|
||||
feature_id = self.feature_1.key.integer_id()
|
||||
params = {"featureId": feature_id}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
self.handler.do_post()
|
||||
updated_feature = models.Feature.get_by_id(feature_id)
|
||||
self.assertEqual(1, updated_feature.star_count)
|
||||
|
||||
params = {"featureId": feature_id, "starred": False}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
self.handler.do_post()
|
||||
updated_feature = models.Feature.get_by_id(feature_id)
|
||||
self.assertEqual(0, updated_feature.star_count)
|
||||
self.assertEqual(0, updated_feature.star_count)
|
||||
|
|
|
@ -21,10 +21,10 @@ import flask
|
|||
import mock
|
||||
import werkzeug.exceptions # Flask HTTP stuff.
|
||||
|
||||
from api import register
|
||||
from api import token_refresh_api
|
||||
from framework import xsrf
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class TokenRefreshAPITest(testing_config.CustomTestCase):
|
||||
|
@ -43,7 +43,7 @@ class TokenRefreshAPITest(testing_config.CustomTestCase):
|
|||
|
||||
def test_do_get(self):
|
||||
"""This handler does not respond to GET requests."""
|
||||
with register.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(NotImplementedError):
|
||||
self.handler.do_get()
|
||||
|
||||
|
@ -51,7 +51,7 @@ class TokenRefreshAPITest(testing_config.CustomTestCase):
|
|||
"""We reject token requests from signed out users."""
|
||||
testing_config.sign_out()
|
||||
params = {}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.post()
|
||||
|
||||
|
@ -59,7 +59,7 @@ class TokenRefreshAPITest(testing_config.CustomTestCase):
|
|||
"""We reject token requests that do not include a previous token."""
|
||||
testing_config.sign_in('user@example.com', 111)
|
||||
params = {}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.post()
|
||||
|
||||
|
@ -69,7 +69,7 @@ class TokenRefreshAPITest(testing_config.CustomTestCase):
|
|||
testing_config.sign_in('user@example.com', 111)
|
||||
mock_validate_token.side_effect = xsrf.TokenIncorrect()
|
||||
params = {'token': 'bad'}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
with self.assertRaises(werkzeug.exceptions.BadRequest):
|
||||
self.handler.post()
|
||||
mock_validate_token.assert_called_once()
|
||||
|
@ -78,7 +78,7 @@ class TokenRefreshAPITest(testing_config.CustomTestCase):
|
|||
"""If the request is accepted, we return a new token."""
|
||||
testing_config.sign_in('user@example.com', 111)
|
||||
params = {'token': 'checked in base class'}
|
||||
with register.app.test_request_context(self.request_path, json=params):
|
||||
with test_app.test_request_context(self.request_path, json=params):
|
||||
actual = self.handler.do_post()
|
||||
self.assertIn('token', actual)
|
||||
self.assertIn('token_expires_sec', actual)
|
||||
self.assertIn('token_expires_sec', actual)
|
||||
|
|
109
app-py2.yaml
109
app-py2.yaml
|
@ -1,5 +1,5 @@
|
|||
# TODO(jrobbins): This GAE service will eventually be almost emptied
|
||||
# out as most handlers are moved over to app-p3.yaml.
|
||||
# This GAE service only contains email related handlers because those
|
||||
# require py2. Everything else is routed through app-py3.yaml.
|
||||
|
||||
runtime: python27
|
||||
threadsafe: false
|
||||
|
@ -17,35 +17,6 @@ builtins:
|
|||
|
||||
handlers:
|
||||
|
||||
# Static handlers ---------------------------------------------------------------
|
||||
- url: /favicon\.ico
|
||||
static_files: static/img/chromium-128.png
|
||||
upload: static/img/chromium-128\.png
|
||||
secure: always
|
||||
|
||||
- url: /robots\.txt
|
||||
static_files: static/robots.txt
|
||||
upload: static/robots\.txt
|
||||
secure: always
|
||||
|
||||
- url: /static
|
||||
static_dir: static
|
||||
#expiration: 30s
|
||||
application_readable: true # So static assets can be read by inline_file django tag.
|
||||
http_headers:
|
||||
Access-Control-Allow-Origin: "*"
|
||||
secure: always
|
||||
|
||||
# Metrics data handlers --------------------------------------------------------
|
||||
- url: /data/.*
|
||||
script: api.metricsdata.app
|
||||
secure: always
|
||||
|
||||
# Admin ------------------------------------------------------------------------
|
||||
- url: /cron/.*
|
||||
script: internals.fetchmetrics.app
|
||||
# Any cron job must be harmless if it is called too often or with bad args
|
||||
|
||||
# Note: This handler must remain in this file because it requires GAE py2.
|
||||
- url: /tasks/outbound-email
|
||||
script: internals.sendemail.app
|
||||
|
@ -57,79 +28,6 @@ handlers:
|
|||
script: internals.sendemail.app
|
||||
login: admin # Prevents raw access to this handler.
|
||||
|
||||
- url: /admin/blink.*
|
||||
script: pages.blink_handler.app
|
||||
secure: always
|
||||
|
||||
- url: /admin/subscribers
|
||||
script: pages.blink_handler.app
|
||||
secure: always
|
||||
|
||||
- url: /admin/features/.*
|
||||
script: pages.intentpreview.app
|
||||
secure: always
|
||||
|
||||
- url: /guide/.*
|
||||
script: pages.guide.app
|
||||
secure: always
|
||||
|
||||
- url: /admin/users/.*
|
||||
script: pages.users.app
|
||||
secure: always
|
||||
|
||||
- url: /settings
|
||||
script: pages.users.app
|
||||
secure: always
|
||||
|
||||
# Main server handlers ---------------------------------------------------------
|
||||
- url: /
|
||||
script: pages.featurelist.app
|
||||
secure: always
|
||||
|
||||
- url: /roadmap
|
||||
script: pages.roadmap.app
|
||||
secure: always
|
||||
|
||||
- url: /features/schedule
|
||||
script: pages.schedule.app
|
||||
secure: always
|
||||
|
||||
- url: /features.*
|
||||
script: pages.featurelist.app
|
||||
secure: always
|
||||
|
||||
- url: /feature/.*
|
||||
script: pages.featuredetail.app
|
||||
secure: always
|
||||
|
||||
- url: /myfeatures
|
||||
script: pages.myfeatures.app
|
||||
secure: always
|
||||
|
||||
- url: /samples.*
|
||||
script: pages.samples.app
|
||||
secure: always
|
||||
|
||||
- url: /metrics.*
|
||||
script: pages.metrics.app
|
||||
secure: always
|
||||
|
||||
- url: /omaha_data
|
||||
script: pages.metrics.app
|
||||
secure: always
|
||||
|
||||
- url: /api/.*
|
||||
script: api.register.app
|
||||
secure: always
|
||||
|
||||
- url: /csp
|
||||
script: framework.csp.app
|
||||
secure: always
|
||||
|
||||
|
||||
includes:
|
||||
- env_vars.yaml
|
||||
|
||||
inbound_services:
|
||||
- mail
|
||||
- mail_bounce
|
||||
|
@ -139,6 +37,3 @@ libraries:
|
|||
version: 1.0.0
|
||||
- name: ssl
|
||||
version: latest
|
||||
|
||||
env_variables:
|
||||
GAE_USE_SOCKETS_HTTPLIB : ''
|
||||
|
|
29
app-py3.yaml
29
app-py3.yaml
|
@ -1,9 +1,32 @@
|
|||
# TODO(jrobbins): This file is not used yet.
|
||||
# It will contain lines to configure a GAE service running in py3.
|
||||
# This GAE service contains most of the app, including all UI pages.
|
||||
|
||||
runtime: python39
|
||||
service: app-py3
|
||||
|
||||
handlers:
|
||||
- url: /hello
|
||||
# Static handlers ---------------------------------------------------------------
|
||||
- url: /favicon\.ico
|
||||
static_files: static/img/chromium-128.png
|
||||
upload: static/img/chromium-128\.png
|
||||
secure: always
|
||||
|
||||
- url: /robots\.txt
|
||||
static_files: static/robots.txt
|
||||
upload: static/robots\.txt
|
||||
secure: always
|
||||
|
||||
- url: /static
|
||||
static_dir: static
|
||||
http_headers:
|
||||
Access-Control-Allow-Origin: "*"
|
||||
secure: always
|
||||
|
||||
- url: /.*
|
||||
script: auto
|
||||
secure: always
|
||||
|
||||
includes:
|
||||
- env_vars.yaml
|
||||
|
||||
env_variables:
|
||||
GAE_USE_SOCKETS_HTTPLIB : ''
|
||||
|
|
|
@ -11,7 +11,8 @@ dispatch:
|
|||
- url: "*/tasks/email-subscribers"
|
||||
service: notifier
|
||||
|
||||
- url: "*/hello"
|
||||
service: app-py3
|
||||
- url: "*/tasks/outbound-email"
|
||||
service: default
|
||||
|
||||
# TODO(jrobbins): Gradually route most requests to service app-py3.
|
||||
- url: "*/*"
|
||||
service: app-py3
|
||||
|
|
|
@ -116,9 +116,6 @@ def get_headers(nonce):
|
|||
return {csp_header_key: csp_directives}
|
||||
|
||||
|
||||
app = flask.Flask(__name__)
|
||||
|
||||
@app.route('/csp', methods=['POST'])
|
||||
def report_handler():
|
||||
"""Log any CSP violations that are reported to our app."""
|
||||
logging.error('CSP Violation: %r' % flask.request.data)
|
||||
|
|
|
@ -18,11 +18,14 @@
|
|||
import unittest
|
||||
import testing_config # Must be imported before the module under test.
|
||||
|
||||
import flask
|
||||
import mock
|
||||
import werkzeug.exceptions # Flask HTTP stuff.
|
||||
|
||||
from framework import csp
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class CspTest(unittest.TestCase):
|
||||
|
||||
|
@ -99,7 +102,7 @@ class CspReporttest(unittest.TestCase):
|
|||
@mock.patch('logging.error')
|
||||
def test_report_handler(self, mock_error):
|
||||
"""The report handler logs something for each request."""
|
||||
with csp.app.test_request_context('/csp', data='12345', method='POST'):
|
||||
with test_app.test_request_context('/csp', data='12345', method='POST'):
|
||||
actual = csp.report_handler()
|
||||
|
||||
self.assertEqual('', actual)
|
||||
|
|
|
@ -268,10 +268,3 @@ class BlinkComponentHandler(basehandlers.FlaskHandler):
|
|||
def get_template_data(self):
|
||||
models.BlinkComponent.update_db()
|
||||
return 'Blink components updated'
|
||||
|
||||
|
||||
app = basehandlers.FlaskApplication([
|
||||
('/cron/metrics', YesterdayHandler),
|
||||
('/cron/histograms', HistogramsHandler),
|
||||
('/cron/update_blink_components', BlinkComponentHandler),
|
||||
], debug=settings.DEBUG)
|
||||
|
|
|
@ -27,6 +27,8 @@ import werkzeug
|
|||
from internals import fetchmetrics
|
||||
from internals import models
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class FetchMetricsTest(testing_config.CustomTestCase):
|
||||
|
||||
|
@ -101,7 +103,7 @@ class YesterdayHandlerTest(testing_config.CustomTestCase):
|
|||
mock_FetchAndSaveData.return_value = 200
|
||||
today = datetime.date(2021, 1, 20)
|
||||
|
||||
with fetchmetrics.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.get_template_data(today=today)
|
||||
|
||||
self.assertEqual('Success', actual_response)
|
||||
|
@ -117,7 +119,7 @@ class YesterdayHandlerTest(testing_config.CustomTestCase):
|
|||
mock_FetchAndSaveData.return_value = 200
|
||||
today = datetime.date(2021, 1, 20)
|
||||
|
||||
with fetchmetrics.app.test_request_context(
|
||||
with test_app.test_request_context(
|
||||
self.request_path, query_string={'date': '20210120'}):
|
||||
actual_response = self.handler.get_template_data(today=today)
|
||||
|
||||
|
@ -174,7 +176,7 @@ class HistogramsHandlerTest(testing_config.CustomTestCase):
|
|||
mock_requests_get.return_value = testing_config.Blank(
|
||||
status_code=200,
|
||||
content=base64.b64encode(self.ENUMS_TEXT.encode()))
|
||||
with fetchmetrics.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.get_template_data()
|
||||
|
||||
self.assertEqual('Success', actual_response)
|
||||
|
|
|
@ -591,6 +591,7 @@ class Feature(DictModel):
|
|||
# TODO(jrobbins): Eliminate format version 1.
|
||||
def format_for_template(self, version=2):
|
||||
self.migrate_views()
|
||||
logging.info('In format_for_template for %r', self)
|
||||
d = self.to_dict()
|
||||
is_released = self.impl_status_chrome in RELEASE_IMPL_STATES
|
||||
d['is_released'] = is_released
|
||||
|
|
174
main.py
174
main.py
|
@ -1,18 +1,176 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2021 Google Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from flask import Flask
|
||||
import logging
|
||||
|
||||
from api import accounts_api
|
||||
from api import approvals_api
|
||||
from api import channels_api
|
||||
from api import comments_api
|
||||
from api import cues_api
|
||||
from api import features_api
|
||||
from api import login_api
|
||||
from api import logout_api
|
||||
from api import metricsdata
|
||||
from api import stars_api
|
||||
from api import token_refresh_api
|
||||
from framework import basehandlers
|
||||
from framework import csp
|
||||
from internals import fetchmetrics
|
||||
from pages import blink_handler
|
||||
from pages import featuredetail
|
||||
from pages import featurelist
|
||||
from pages import guide
|
||||
from pages import intentpreview
|
||||
from pages import metrics
|
||||
from pages import myfeatures
|
||||
from pages import roadmap
|
||||
from pages import samples
|
||||
from pages import schedule
|
||||
from pages import users
|
||||
import settings
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
# If `entrypoint` is not defined in app.yaml, App Engine will look for an app
|
||||
# called `app` in `main.py`.
|
||||
app = Flask(__name__)
|
||||
|
||||
metrics_chart_routes = [
|
||||
('/data/timeline/cssanimated', metricsdata.AnimatedTimelineHandler),
|
||||
('/data/timeline/csspopularity', metricsdata.PopularityTimelineHandler),
|
||||
('/data/timeline/featurepopularity',
|
||||
metricsdata.FeatureObserverTimelineHandler),
|
||||
('/data/csspopularity', metricsdata.CSSPopularityHandler),
|
||||
('/data/cssanimated', metricsdata.CSSAnimatedHandler),
|
||||
('/data/featurepopularity', metricsdata.FeatureObserverPopularityHandler),
|
||||
('/data/blink/<string:prop_type>', metricsdata.FeatureBucketsHandler),
|
||||
]
|
||||
|
||||
# TODO(jrobbins): Advance this to v1 once we have it fleshed out
|
||||
API_BASE = '/api/v0'
|
||||
api_routes = [
|
||||
(API_BASE + '/features', features_api.FeaturesAPI),
|
||||
(API_BASE + '/features/<int:feature_id>', features_api.FeaturesAPI),
|
||||
(API_BASE + '/features/<int:feature_id>/approvals/<int:field_id>',
|
||||
approvals_api.ApprovalsAPI),
|
||||
(API_BASE + '/features/<int:feature_id>/approvals/<int:field_id>/comments',
|
||||
comments_api.CommentsAPI),
|
||||
|
||||
(API_BASE + '/login', login_api.LoginAPI),
|
||||
(API_BASE + '/logout', logout_api.LogoutAPI),
|
||||
(API_BASE + '/currentuser/stars', stars_api.StarsAPI),
|
||||
(API_BASE + '/currentuser/cues', cues_api.CuesAPI),
|
||||
(API_BASE + '/currentuser/token', token_refresh_api.TokenRefreshAPI),
|
||||
# (API_BASE + '/currentuser/autosaves', TODO),
|
||||
# (API_BASE + '/currentuser/settings', TODO),
|
||||
|
||||
# Admin operations for user accounts
|
||||
(API_BASE + '/accounts', accounts_api.AccountsAPI),
|
||||
(API_BASE + '/accounts/<int:account_id>', accounts_api.AccountsAPI),
|
||||
|
||||
(API_BASE + '/channels', channels_api.ChannelsAPI), # omaha data
|
||||
# (API_BASE + '/schedule', TODO), # chromiumdash data
|
||||
# (API_BASE + '/metrics/<str:kind>', TODO), # uma-export data
|
||||
# (API_BASE + '/metrics/<str:kind>/<int:bucket_id>', TODO),
|
||||
]
|
||||
|
||||
|
||||
@app.route('/hello')
|
||||
def hello():
|
||||
"""Return a friendly HTTP greeting."""
|
||||
logging.info('In hello() !')
|
||||
return 'Hello python 3!'
|
||||
page_routes = [
|
||||
('/admin/subscribers', blink_handler.SubscribersHandler),
|
||||
('/admin/blink', blink_handler.BlinkHandler),
|
||||
|
||||
('/feature/<int:feature_id>', featuredetail.FeatureDetailHandler),
|
||||
|
||||
# Note: The only requests being made now hit /features.json and
|
||||
# /features_v2.json, but both of those cause version == 2.
|
||||
# There was logic to accept another version value, but it it was not used.
|
||||
(r'/features.json', featurelist.FeaturesJsonHandler),
|
||||
(r'/features_v2.json', featurelist.FeaturesJsonHandler),
|
||||
|
||||
('/', basehandlers.Redirector,
|
||||
{'location': '/features'}),
|
||||
|
||||
('/features', featurelist.FeatureListHandler),
|
||||
('/features/<int:feature_id>', featurelist.FeatureListHandler),
|
||||
('/features.xml', featurelist.FeatureListXMLHandler),
|
||||
|
||||
('/guide/new', guide.FeatureNew),
|
||||
('/guide/edit/<int:feature_id>', guide.ProcessOverview),
|
||||
('/guide/stage/<int:feature_id>/<int:stage_id>', guide.FeatureEditStage),
|
||||
('/guide/editall/<int:feature_id>', guide.FeatureEditAllFields),
|
||||
|
||||
('/admin/features/launch/<int:feature_id>',
|
||||
intentpreview.IntentEmailPreviewHandler),
|
||||
('/admin/features/launch/<int:feature_id>/<int:stage_id>',
|
||||
intentpreview.IntentEmailPreviewHandler),
|
||||
|
||||
('/metrics', basehandlers.Redirector,
|
||||
{'location': '/metrics/css/popularity'}),
|
||||
('/metrics/css', basehandlers.Redirector,
|
||||
{'location': '/metrics/css/popularity'}),
|
||||
|
||||
# TODO(jrobbins): These seem like they belong in metrics.py.
|
||||
('/metrics/css/popularity', basehandlers.ConstHandler,
|
||||
{'template_path': 'metrics/css/popularity.html'}),
|
||||
('/metrics/css/animated', basehandlers.ConstHandler,
|
||||
{'template_path': 'metrics/css/animated.html'}),
|
||||
('/metrics/css/timeline/popularity', metrics.CssPopularityHandler),
|
||||
('/metrics/css/timeline/popularity/<int:bucket_id>',
|
||||
metrics.CssPopularityHandler),
|
||||
('/metrics/css/timeline/animated', metrics.CssAnimatedHandler),
|
||||
('/metrics/css/timeline/animated/<int:bucket_id>',
|
||||
metrics.CssAnimatedHandler),
|
||||
('/metrics/feature/popularity', basehandlers.ConstHandler,
|
||||
{'template_path': 'metrics/feature/popularity.html'}),
|
||||
('/metrics/feature/timeline/popularity', metrics.FeaturePopularityHandler),
|
||||
('/metrics/feature/timeline/popularity/<int:bucket_id>',
|
||||
metrics.FeaturePopularityHandler),
|
||||
('/omaha_data', metrics.OmahaDataHandler),
|
||||
|
||||
('/myfeatures', myfeatures.MyFeaturesHandler),
|
||||
|
||||
('/roadmap', roadmap.RoadmapHandler),
|
||||
|
||||
('/samples', samples.SamplesHandler),
|
||||
('/samples.json', samples.SamplesJSONHandler),
|
||||
('/samples.xml', samples.SamplesXMLHandler),
|
||||
|
||||
('/features/schedule', schedule.ScheduleHandler),
|
||||
|
||||
('/settings', users.SettingsHandler),
|
||||
('/admin/users/new', users.UserListHandler),
|
||||
]
|
||||
|
||||
|
||||
internals_routes = [
|
||||
('/cron/metrics', fetchmetrics.YesterdayHandler),
|
||||
('/cron/histograms', fetchmetrics.HistogramsHandler),
|
||||
('/cron/update_blink_components', fetchmetrics.BlinkComponentHandler),
|
||||
]
|
||||
|
||||
|
||||
# All requests to the app-py3 GAE service are handled by this Flask app.
|
||||
app = basehandlers.FlaskApplication(
|
||||
(metrics_chart_routes + api_routes + page_routes +
|
||||
internals_routes),
|
||||
debug=settings.DEBUG)
|
||||
|
||||
# TODO(jrobbins): Make the CSP handler be a class like our others.
|
||||
app.add_url_rule(
|
||||
'/csp', view_func=csp.report_handler,
|
||||
methods=['POST'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# This is used when running locally only. When deploying to Google App
|
||||
|
|
|
@ -22,47 +22,12 @@ import collections
|
|||
import json
|
||||
import logging
|
||||
import os
|
||||
import yaml
|
||||
|
||||
from framework import basehandlers
|
||||
from framework import permissions
|
||||
from internals import models
|
||||
import settings
|
||||
from .schedule import construct_chrome_channels_details
|
||||
|
||||
|
||||
class PopulateSubscribersHandler(basehandlers.FlaskHandler):
|
||||
|
||||
def __populate_subscribers(self):
|
||||
"""Seeds the database with the team in devrel_team.yaml and adds the team
|
||||
member to the specified blink components in that file. Should only be ran
|
||||
if the FeatureOwner database entries have been cleared"""
|
||||
f = file('%s/data/devrel_team.yaml' % settings.ROOT_DIR, 'r')
|
||||
for profile in yaml.load_all(f):
|
||||
blink_components = profile.get('blink_components', [])
|
||||
blink_components = [
|
||||
models.BlinkComponent.get_by_name(name).key
|
||||
for name in blink_components]
|
||||
blink_components = [f for f in blink_components if f]
|
||||
|
||||
user = models.FeatureOwner(
|
||||
name=str(profile['name']),
|
||||
email=str(profile['email']),
|
||||
twitter=profile.get('twitter', None),
|
||||
blink_components=blink_components,
|
||||
primary_blink_components=blink_components,
|
||||
watching_all_features=False,
|
||||
)
|
||||
user.put()
|
||||
f.close()
|
||||
|
||||
@permissions.require_admin_site
|
||||
def get_template_data(self):
|
||||
if settings.PROD:
|
||||
return 'Handler not allowed in production.'
|
||||
models.BlinkComponent.update_db()
|
||||
self.__populate_subscribers()
|
||||
return self.redirect('/admin/blink')
|
||||
from pages.schedule import construct_chrome_channels_details
|
||||
|
||||
|
||||
class BlinkHandler(basehandlers.FlaskHandler):
|
||||
|
@ -182,10 +147,3 @@ class SubscribersHandler(basehandlers.FlaskHandler):
|
|||
'selected_milestone': int(milestone) if milestone else None
|
||||
}
|
||||
return template_data
|
||||
|
||||
|
||||
app = basehandlers.FlaskApplication([
|
||||
('/admin/blink/populate_subscribers', PopulateSubscribersHandler),
|
||||
('/admin/subscribers', SubscribersHandler),
|
||||
('/admin/blink', BlinkHandler),
|
||||
], debug=settings.DEBUG)
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
import json
|
||||
import logging
|
||||
|
||||
import settings
|
||||
from framework import basehandlers
|
||||
from pages import guideforms
|
||||
from internals import models
|
||||
|
@ -52,10 +51,3 @@ class FeatureDetailHandler(basehandlers.FlaskHandler):
|
|||
'new_crbug_url': f.new_crbug_url(),
|
||||
}
|
||||
return template_data
|
||||
|
||||
|
||||
routes = [
|
||||
('/feature/<int:feature_id>', FeatureDetailHandler),
|
||||
]
|
||||
|
||||
app = basehandlers.FlaskApplication(routes, debug=settings.DEBUG)
|
||||
|
|
|
@ -25,6 +25,8 @@ from internals import models
|
|||
from framework import ramcache
|
||||
from pages import featuredetail
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class TestWithFeature(testing_config.CustomTestCase):
|
||||
|
||||
|
@ -58,7 +60,7 @@ class FeatureDetailHandlerTest(TestWithFeature):
|
|||
def test_get_template_data__missing(self):
|
||||
"""If a feature is not found, give a 404."""
|
||||
feature_id = 123456
|
||||
with featuredetail.app.test_request_context('/feature/123456'):
|
||||
with test_app.test_request_context('/feature/123456'):
|
||||
with self.assertRaises(werkzeug.exceptions.NotFound):
|
||||
self.handler.get_template_data(feature_id=feature_id)
|
||||
|
||||
|
@ -69,14 +71,14 @@ class FeatureDetailHandlerTest(TestWithFeature):
|
|||
self.feature_1.deleted = True
|
||||
self.feature_1.put()
|
||||
|
||||
with featuredetail.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.NotFound):
|
||||
template_data = self.handler.get_template_data(
|
||||
feature_id=self.feature_id)
|
||||
|
||||
def test_get_template_data__normal(self):
|
||||
"""We can prep to render the feature detail page."""
|
||||
with featuredetail.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
template_data = self.handler.get_template_data(
|
||||
feature_id=self.feature_id)
|
||||
|
||||
|
@ -90,7 +92,7 @@ class FeatureDetailTemplateTest(TestWithFeature):
|
|||
|
||||
def setUp(self):
|
||||
super(FeatureDetailTemplateTest, self).setUp()
|
||||
with featuredetail.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
self.template_data = self.handler.get_template_data(
|
||||
feature_id=self.feature_id)
|
||||
|
||||
|
|
|
@ -105,21 +105,3 @@ class FeatureListXMLHandler(basehandlers.FlaskHandler):
|
|||
version=2)
|
||||
|
||||
return utils.render_atom_feed(self.request, 'Features', feature_list)
|
||||
|
||||
|
||||
routes = [
|
||||
# Note: The only requests being made now hit /features.json and
|
||||
# /features_v2.json, but both of those cause version == 2.
|
||||
# There was logic to accept another version value, but it it was not used.
|
||||
(r'/features.json', FeaturesJsonHandler),
|
||||
(r'/features_v2.json', FeaturesJsonHandler),
|
||||
|
||||
('/', basehandlers.Redirector,
|
||||
{'location': '/features'}),
|
||||
|
||||
('/features', FeatureListHandler),
|
||||
('/features/<int:feature_id>', FeatureListHandler),
|
||||
('/features.xml', FeatureListXMLHandler),
|
||||
]
|
||||
|
||||
app = basehandlers.FlaskApplication(routes, debug=settings.DEBUG)
|
||||
|
|
|
@ -24,6 +24,8 @@ from framework import ramcache
|
|||
from internals import models
|
||||
from pages import featurelist
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class TestWithFeature(testing_config.CustomTestCase):
|
||||
|
||||
|
@ -57,7 +59,7 @@ class FeaturesJsonHandlerTest(TestWithFeature):
|
|||
def test_get_template_data(self):
|
||||
"""User can get a JSON feed of all features."""
|
||||
testing_config.sign_in('user@example.com', 111)
|
||||
with featurelist.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
json_data = self.handler.get_template_data()
|
||||
|
||||
self.assertEqual(1, len(json_data))
|
||||
|
@ -69,12 +71,12 @@ class FeaturesJsonHandlerTest(TestWithFeature):
|
|||
self.feature_1.put()
|
||||
|
||||
testing_config.sign_out()
|
||||
with featurelist.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
json_data = self.handler.get_template_data()
|
||||
self.assertEqual(0, len(json_data))
|
||||
|
||||
testing_config.sign_in('user@example.com', 111)
|
||||
with featurelist.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
json_data = self.handler.get_template_data()
|
||||
self.assertEqual(0, len(json_data))
|
||||
|
||||
|
@ -84,7 +86,7 @@ class FeaturesJsonHandlerTest(TestWithFeature):
|
|||
self.feature_1.put()
|
||||
|
||||
testing_config.sign_in('user@google.com', 111)
|
||||
with featurelist.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
json_data = self.handler.get_template_data()
|
||||
self.assertEqual(1, len(json_data))
|
||||
self.assertEqual('feature one', json_data[0]['name'])
|
||||
|
@ -97,7 +99,7 @@ class FeatureListHandlerTest(TestWithFeature):
|
|||
|
||||
def test_get_template_data(self):
|
||||
"""User can get a feature list page."""
|
||||
with featurelist.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
template_data = self.handler.get_template_data()
|
||||
|
||||
self.assertIn('IMPLEMENTATION_STATUSES', template_data)
|
||||
|
@ -110,7 +112,7 @@ class FeatureListXMLHandlerTest(TestWithFeature):
|
|||
|
||||
def test_get_template_data__no_filters(self):
|
||||
"""User can get an XML feed of all features."""
|
||||
with featurelist.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_text, actual_headers = self.handler.get_template_data()
|
||||
|
||||
self.assertTrue(actual_text.startswith('<?xml'))
|
||||
|
@ -123,7 +125,7 @@ class FeatureListXMLHandlerTest(TestWithFeature):
|
|||
def test_get_template_data__category(self):
|
||||
"""User can get an XML feed of features by category."""
|
||||
request_path = self.request_path + '?category=web components'
|
||||
with featurelist.app.test_request_context(request_path):
|
||||
with test_app.test_request_context(request_path):
|
||||
actual_text, actual_headers = self.handler.get_template_data()
|
||||
|
||||
# It is an XML feed
|
||||
|
@ -138,8 +140,8 @@ class FeatureListXMLHandlerTest(TestWithFeature):
|
|||
|
||||
|
||||
request_path = self.request_path + '?category=css'
|
||||
with featurelist.app.test_request_context(request_path):
|
||||
with test_app.test_request_context(request_path):
|
||||
actual_text, actual_headers = self.handler.get_template_data()
|
||||
|
||||
self.assertTrue(actual_text.startswith('<?xml'))
|
||||
self.assertNotIn('feature one', actual_text)
|
||||
self.assertNotIn('feature one', actual_text)
|
||||
|
|
|
@ -36,7 +36,6 @@ from framework import utils
|
|||
from pages import guideforms
|
||||
from internals import models
|
||||
from internals import processes
|
||||
import settings
|
||||
|
||||
|
||||
# Forms to be used for each stage of each process.
|
||||
|
@ -563,11 +562,3 @@ class FeatureEditAllFields(FeatureEditStage):
|
|||
'flat_forms': flat_forms,
|
||||
}
|
||||
return template_data
|
||||
|
||||
|
||||
app = basehandlers.FlaskApplication([
|
||||
('/guide/new', FeatureNew),
|
||||
('/guide/edit/<int:feature_id>', ProcessOverview),
|
||||
('/guide/stage/<int:feature_id>/<int:stage_id>', FeatureEditStage),
|
||||
('/guide/editall/<int:feature_id>', FeatureEditAllFields),
|
||||
], debug=settings.DEBUG)
|
||||
|
|
|
@ -25,6 +25,9 @@ from internals import models
|
|||
from pages import guide
|
||||
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class FeatureNewTest(testing_config.CustomTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -33,21 +36,21 @@ class FeatureNewTest(testing_config.CustomTestCase):
|
|||
def test_get__anon(self):
|
||||
"""Anon cannot create features, gets a redirect to sign in page."""
|
||||
testing_config.sign_out()
|
||||
with guide.app.test_request_context('/guide/new'):
|
||||
with test_app.test_request_context('/guide/new'):
|
||||
actual_response = self.handler.get_template_data()
|
||||
self.assertEqual('302 FOUND', actual_response.status)
|
||||
|
||||
def test_get__non_allowed(self):
|
||||
"""Non-allowed cannot create features, gets a 403."""
|
||||
testing_config.sign_in('user1@example.com', 1234567890)
|
||||
with guide.app.test_request_context('/guide/new'):
|
||||
with test_app.test_request_context('/guide/new'):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
actual_response = self.handler.get_template_data()
|
||||
|
||||
def test_get__normal(self):
|
||||
"""Allowed users render a page with a django form."""
|
||||
testing_config.sign_in('user1@google.com', 1234567890)
|
||||
with guide.app.test_request_context('/guide/new'):
|
||||
with test_app.test_request_context('/guide/new'):
|
||||
template_data = self.handler.get_template_data()
|
||||
|
||||
self.assertTrue('overview_form' in template_data)
|
||||
|
@ -60,21 +63,21 @@ class FeatureNewTest(testing_config.CustomTestCase):
|
|||
def test_post__anon(self):
|
||||
"""Anon cannot create features, gets a 403."""
|
||||
testing_config.sign_out()
|
||||
with guide.app.test_request_context('/guide/new', method='POST'):
|
||||
with test_app.test_request_context('/guide/new', method='POST'):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.process_post_data()
|
||||
|
||||
def test_post__non_allowed(self):
|
||||
"""Non-allowed cannot create features, gets a 403."""
|
||||
testing_config.sign_in('user1@example.com', 1234567890)
|
||||
with guide.app.test_request_context('/guide/new', method='POST'):
|
||||
with test_app.test_request_context('/guide/new', method='POST'):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.post()
|
||||
|
||||
def test_post__normal_valid(self):
|
||||
"""Allowed user can create a feature."""
|
||||
testing_config.sign_in('user1@google.com', 1234567890)
|
||||
with guide.app.test_request_context(
|
||||
with test_app.test_request_context(
|
||||
'/guide/new', data={
|
||||
'category': '1',
|
||||
'name': 'Feature name',
|
||||
|
@ -128,7 +131,7 @@ class ProcessOverviewTest(testing_config.CustomTestCase):
|
|||
def test_get__anon(self):
|
||||
"""Anon cannot edit features, gets a redirect to viewing page."""
|
||||
testing_config.sign_out()
|
||||
with guide.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.get_template_data(
|
||||
self.feature_1.key.integer_id())
|
||||
self.assertEqual('302 FOUND', actual_response.status)
|
||||
|
@ -136,7 +139,7 @@ class ProcessOverviewTest(testing_config.CustomTestCase):
|
|||
def test_get__non_allowed(self):
|
||||
"""Non-allowed cannot create features, gets a 403."""
|
||||
testing_config.sign_in('user1@example.com', 1234567890)
|
||||
with guide.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.get_template_data(self.feature_1.key.integer_id())
|
||||
|
||||
|
@ -144,7 +147,7 @@ class ProcessOverviewTest(testing_config.CustomTestCase):
|
|||
def test_get__not_found(self):
|
||||
"""Allowed users get a 404 if there is no such feature."""
|
||||
testing_config.sign_in('user1@google.com', 1234567890)
|
||||
with guide.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.NotFound):
|
||||
self.handler.get_template_data(999)
|
||||
|
||||
|
@ -152,7 +155,7 @@ class ProcessOverviewTest(testing_config.CustomTestCase):
|
|||
"""Allowed users render a page with a process overview."""
|
||||
testing_config.sign_in('user1@google.com', 1234567890)
|
||||
|
||||
with guide.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
template_data = self.handler.get_template_data(
|
||||
self.feature_1.key.integer_id())
|
||||
|
||||
|
@ -179,14 +182,14 @@ class FeatureEditStageTest(testing_config.CustomTestCase):
|
|||
|
||||
def test_touched(self):
|
||||
"""We can tell if the user meant to edit a field."""
|
||||
with guide.app.test_request_context(
|
||||
with test_app.test_request_context(
|
||||
'path', data={'name': 'new name'}):
|
||||
self.assertTrue(self.handler.touched('name'))
|
||||
self.assertFalse(self.handler.touched('summary'))
|
||||
|
||||
def test_split_input(self):
|
||||
"""We can parse items from multi-item text fields"""
|
||||
with guide.app.test_request_context(
|
||||
with test_app.test_request_context(
|
||||
'path', data={
|
||||
'empty': '',
|
||||
'colors': 'yellow\nblue',
|
||||
|
@ -204,7 +207,7 @@ class FeatureEditStageTest(testing_config.CustomTestCase):
|
|||
def test_get__anon(self):
|
||||
"""Anon cannot edit features, gets a redirect to viewing page."""
|
||||
testing_config.sign_out()
|
||||
with guide.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.get_template_data(
|
||||
self.feature_1.key.integer_id(), self.stage)
|
||||
self.assertEqual('302 FOUND', actual_response.status)
|
||||
|
@ -212,7 +215,7 @@ class FeatureEditStageTest(testing_config.CustomTestCase):
|
|||
def test_get__non_allowed(self):
|
||||
"""Non-allowed cannot edit features, gets a 403."""
|
||||
testing_config.sign_in('user1@example.com', 1234567890)
|
||||
with guide.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.get_template_data(
|
||||
self.feature_1.key.integer_id(), self.stage)
|
||||
|
@ -220,7 +223,7 @@ class FeatureEditStageTest(testing_config.CustomTestCase):
|
|||
def test_get__not_found(self):
|
||||
"""Allowed users get a 404 if there is no such feature."""
|
||||
testing_config.sign_in('user1@google.com', 1234567890)
|
||||
with guide.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.NotFound):
|
||||
self.handler.get_template_data(999, self.stage)
|
||||
|
||||
|
@ -228,7 +231,7 @@ class FeatureEditStageTest(testing_config.CustomTestCase):
|
|||
"""Allowed users render a page with a django form."""
|
||||
testing_config.sign_in('user1@google.com', 1234567890)
|
||||
|
||||
with guide.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
template_data = self.handler.get_template_data(
|
||||
self.feature_1.key.integer_id(), self.stage)
|
||||
|
||||
|
@ -241,7 +244,7 @@ class FeatureEditStageTest(testing_config.CustomTestCase):
|
|||
"""When feature is not on the stage for the current form, offer checkbox."""
|
||||
testing_config.sign_in('user1@google.com', 1234567890)
|
||||
|
||||
with guide.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
template_data = self.handler.get_template_data(
|
||||
self.feature_1.key.integer_id(), self.stage)
|
||||
|
||||
|
@ -253,7 +256,7 @@ class FeatureEditStageTest(testing_config.CustomTestCase):
|
|||
self.feature_1.put()
|
||||
testing_config.sign_in('user1@google.com', 1234567890)
|
||||
|
||||
with guide.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
template_data = self.handler.get_template_data(
|
||||
self.feature_1.key.integer_id(), self.stage)
|
||||
|
||||
|
@ -262,7 +265,7 @@ class FeatureEditStageTest(testing_config.CustomTestCase):
|
|||
def test_post__anon(self):
|
||||
"""Anon cannot edit features, gets a 403."""
|
||||
testing_config.sign_out()
|
||||
with guide.app.test_request_context(self.request_path, method='POST'):
|
||||
with test_app.test_request_context(self.request_path, method='POST'):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.process_post_data(
|
||||
self.feature_1.key.integer_id(), self.stage)
|
||||
|
@ -270,7 +273,7 @@ class FeatureEditStageTest(testing_config.CustomTestCase):
|
|||
def test_post__non_allowed(self):
|
||||
"""Non-allowed cannot edit features, gets a 403."""
|
||||
testing_config.sign_in('user1@example.com', 1234567890)
|
||||
with guide.app.test_request_context(self.request_path, method='POST'):
|
||||
with test_app.test_request_context(self.request_path, method='POST'):
|
||||
with self.assertRaises(werkzeug.exceptions.Forbidden):
|
||||
self.handler.process_post_data(
|
||||
self.feature_1.key.integer_id(), self.stage)
|
||||
|
@ -278,7 +281,7 @@ class FeatureEditStageTest(testing_config.CustomTestCase):
|
|||
def test_post__normal_valid(self):
|
||||
"""Allowed user can edit a feature."""
|
||||
testing_config.sign_in('user1@google.com', 1234567890)
|
||||
with guide.app.test_request_context(
|
||||
with test_app.test_request_context(
|
||||
self.request_path, data={
|
||||
'category': '2',
|
||||
'name': 'Revised feature name',
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
from framework import users
|
||||
|
||||
from internals import models
|
||||
import settings
|
||||
from framework import basehandlers
|
||||
from framework import permissions
|
||||
from internals import processes
|
||||
|
@ -84,9 +83,3 @@ class IntentEmailPreviewHandler(basehandlers.FlaskHandler):
|
|||
return 'Intent to Extend Deprecation Trial'
|
||||
|
||||
return 'Intent stage "%s"' % models.INTENT_STAGES[intent_stage]
|
||||
|
||||
app = basehandlers.FlaskApplication([
|
||||
('/admin/features/launch/<int:feature_id>', IntentEmailPreviewHandler),
|
||||
('/admin/features/launch/<int:feature_id>/<int:stage_id>',
|
||||
IntentEmailPreviewHandler),
|
||||
], debug=settings.DEBUG)
|
||||
|
|
|
@ -24,6 +24,7 @@ import werkzeug
|
|||
from pages import intentpreview
|
||||
from internals import models
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class IntentEmailPreviewHandlerTest(testing_config.CustomTestCase):
|
||||
|
@ -46,7 +47,7 @@ class IntentEmailPreviewHandlerTest(testing_config.CustomTestCase):
|
|||
"""Anon cannot view this preview features, gets redirected to login."""
|
||||
testing_config.sign_out()
|
||||
feature_id = self.feature_1.key.integer_id()
|
||||
with intentpreview.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_response = self.handler.get_template_data(feature_id=feature_id)
|
||||
self.assertEqual('302 FOUND', actual_response.status)
|
||||
|
||||
|
@ -54,7 +55,7 @@ class IntentEmailPreviewHandlerTest(testing_config.CustomTestCase):
|
|||
"""Trying to view a feature that does not exist gives a 404."""
|
||||
testing_config.sign_in('user1@google.com', 123567890)
|
||||
bad_feature_id = self.feature_1.key.integer_id() + 1
|
||||
with intentpreview.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
with self.assertRaises(werkzeug.exceptions.NotFound):
|
||||
self.handler.get_template_data(feature_id=bad_feature_id)
|
||||
|
||||
|
@ -64,7 +65,7 @@ class IntentEmailPreviewHandlerTest(testing_config.CustomTestCase):
|
|||
'/admin/features/launch/%d?intent' % self.feature_1.key.integer_id())
|
||||
testing_config.sign_in('user1@google.com', 123567890)
|
||||
feature_id = self.feature_1.key.integer_id()
|
||||
with intentpreview.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_data = self.handler.get_template_data(feature_id=feature_id)
|
||||
self.assertIn('feature', actual_data)
|
||||
self.assertEqual('feature one', actual_data['feature']['name'])
|
||||
|
@ -73,7 +74,7 @@ class IntentEmailPreviewHandlerTest(testing_config.CustomTestCase):
|
|||
"""Allowed user can preview intent email for a feature."""
|
||||
testing_config.sign_in('user1@google.com', 123567890)
|
||||
feature_id = self.feature_1.key.integer_id()
|
||||
with intentpreview.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_data = self.handler.get_template_data(feature_id=feature_id)
|
||||
self.assertIn('feature', actual_data)
|
||||
self.assertEqual('feature one', actual_data['feature']['name'])
|
||||
|
@ -81,7 +82,7 @@ class IntentEmailPreviewHandlerTest(testing_config.CustomTestCase):
|
|||
def test_get_page_data(self):
|
||||
"""page_data has correct values."""
|
||||
feature_id = self.feature_1.key.integer_id()
|
||||
with intentpreview.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
page_data = self.handler.get_page_data(
|
||||
feature_id, self.feature_1, models.INTENT_IMPLEMENT)
|
||||
self.assertEqual(
|
||||
|
@ -162,4 +163,4 @@ class IntentEmailPreviewHandlerTest(testing_config.CustomTestCase):
|
|||
self.assertEqual(
|
||||
'Request for Deprecation Trial',
|
||||
self.handler.compute_subject_prefix(
|
||||
self.feature_1, models.INTENT_EXTEND_TRIAL))
|
||||
self.feature_1, models.INTENT_EXTEND_TRIAL))
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
import json
|
||||
import logging
|
||||
|
||||
import settings
|
||||
from framework import basehandlers
|
||||
from framework import utils
|
||||
from pages import guideforms
|
||||
|
@ -28,9 +27,6 @@ from framework import ramcache
|
|||
from framework import utils
|
||||
from internals import fetchchannels
|
||||
|
||||
from google.appengine.api import users
|
||||
|
||||
|
||||
|
||||
class CssPopularityHandler(basehandlers.FlaskHandler):
|
||||
|
||||
|
@ -75,30 +71,3 @@ class OmahaDataHandler(basehandlers.FlaskHandler):
|
|||
def get_template_data(self):
|
||||
omaha_data = fetchchannels.get_omaha_data()
|
||||
return omaha_data
|
||||
|
||||
|
||||
# Main URL routes.
|
||||
routes = [
|
||||
('/metrics', basehandlers.Redirector,
|
||||
{'location': '/metrics/css/popularity'}),
|
||||
('/metrics/css', basehandlers.Redirector,
|
||||
{'location': '/metrics/css/popularity'}),
|
||||
|
||||
# TODO(jrobbins): These seem like they belong in metrics.py.
|
||||
('/metrics/css/popularity', basehandlers.ConstHandler,
|
||||
{'template_path': 'metrics/css/popularity.html'}),
|
||||
('/metrics/css/animated', basehandlers.ConstHandler,
|
||||
{'template_path': 'metrics/css/animated.html'}),
|
||||
('/metrics/css/timeline/popularity', CssPopularityHandler),
|
||||
('/metrics/css/timeline/popularity/<int:bucket_id>', CssPopularityHandler),
|
||||
('/metrics/css/timeline/animated', CssAnimatedHandler),
|
||||
('/metrics/css/timeline/animated/<int:bucket_id>', CssAnimatedHandler),
|
||||
('/metrics/feature/popularity', basehandlers.ConstHandler,
|
||||
{'template_path': 'metrics/feature/popularity.html'}),
|
||||
('/metrics/feature/timeline/popularity', FeaturePopularityHandler),
|
||||
('/metrics/feature/timeline/popularity/<int:bucket_id>', FeaturePopularityHandler),
|
||||
|
||||
('/omaha_data', OmahaDataHandler),
|
||||
]
|
||||
|
||||
app = basehandlers.FlaskApplication(routes, debug=settings.DEBUG)
|
||||
|
|
|
@ -37,9 +37,3 @@ class MyFeaturesHandler(basehandlers.FlaskHandler):
|
|||
|
||||
template_data = {}
|
||||
return template_data
|
||||
|
||||
routes = [
|
||||
('/myfeatures', MyFeaturesHandler),
|
||||
]
|
||||
|
||||
app = basehandlers.FlaskApplication(routes, debug=settings.DEBUG)
|
||||
|
|
|
@ -26,6 +26,8 @@ from framework import ramcache
|
|||
from internals import models
|
||||
from pages import myfeatures
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class MyFeaturesHandlerTest(testing_config.CustomTestCase):
|
||||
|
||||
|
@ -39,7 +41,7 @@ class MyFeaturesHandlerTest(testing_config.CustomTestCase):
|
|||
mock_gsiup.return_value = None
|
||||
mock_redirect.return_value = 'mock redirect response'
|
||||
|
||||
with myfeatures.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual = self.handler.get_template_data()
|
||||
|
||||
mock_redirect.assert_called_once_with(settings.LOGIN_PAGE_URL)
|
||||
|
@ -50,7 +52,7 @@ class MyFeaturesHandlerTest(testing_config.CustomTestCase):
|
|||
"""User can get a 'my feature' page."""
|
||||
mock_gsiup.return_value = models.UserPref(
|
||||
email='user@example.com')
|
||||
with myfeatures.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
template_data = self.handler.get_template_data()
|
||||
|
||||
# Everything is done in JS, so there is no template_data
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
__author__ = 'shivam.agrawal.2000@gmail.com (Shivam Agarwal)'
|
||||
|
||||
from framework import basehandlers
|
||||
import settings
|
||||
|
||||
|
||||
class RoadmapHandler(basehandlers.FlaskHandler):
|
||||
|
||||
|
@ -27,8 +27,3 @@ class RoadmapHandler(basehandlers.FlaskHandler):
|
|||
|
||||
def get_template_data(self):
|
||||
return {}
|
||||
|
||||
|
||||
app = basehandlers.FlaskApplication([
|
||||
('/roadmap', RoadmapHandler),
|
||||
], debug=settings.DEBUG)
|
||||
|
|
|
@ -67,12 +67,3 @@ class SamplesXMLHandler(basehandlers.FlaskHandler):
|
|||
max_items = settings.RSS_FEED_LIMIT
|
||||
|
||||
return utils.render_atom_feed(self.request, 'Samples', feature_list)
|
||||
|
||||
|
||||
routes = [
|
||||
('/samples', SamplesHandler),
|
||||
('/samples.json', SamplesJSONHandler),
|
||||
('/samples.xml', SamplesXMLHandler),
|
||||
]
|
||||
|
||||
app = basehandlers.FlaskApplication(routes, debug=settings.DEBUG)
|
||||
|
|
|
@ -24,6 +24,8 @@ from internals import models
|
|||
from framework import ramcache
|
||||
from pages import samples
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class TestWithFeature(testing_config.CustomTestCase):
|
||||
|
||||
|
@ -56,7 +58,7 @@ class SamplesHandlerTest(TestWithFeature):
|
|||
|
||||
def test_get_template_data(self):
|
||||
"""User can get a page with all samples."""
|
||||
with samples.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
template_data = self.handler.get_template_data()
|
||||
|
||||
self.assertIn('FEATURES', template_data)
|
||||
|
@ -69,7 +71,7 @@ class SamplesJSONHandlerTest(TestWithFeature):
|
|||
|
||||
def test_get_template_data(self):
|
||||
"""User can get a JSON feed of all samples."""
|
||||
with samples.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
json_data = self.handler.get_template_data()
|
||||
|
||||
self.assertEqual([], json_data)
|
||||
|
@ -82,7 +84,7 @@ class SamplesXMLHandlerTest(TestWithFeature):
|
|||
|
||||
def test_get_template_data(self):
|
||||
"""User can get an XML feed of all samples."""
|
||||
with samples.app.test_request_context(self.request_path):
|
||||
with test_app.test_request_context(self.request_path):
|
||||
actual_text, actual_headers = self.handler.get_template_data()
|
||||
|
||||
# It is an XML feed
|
||||
|
@ -92,4 +94,4 @@ class SamplesXMLHandlerTest(TestWithFeature):
|
|||
|
||||
# feature_1 is not in the list because it does not have a sample.
|
||||
self.assertNotIn('detailed sum', actual_text)
|
||||
self.assertNotIn('feature/' + str(self.feature_id), actual_text)
|
||||
self.assertNotIn('feature/' + str(self.feature_id), actual_text)
|
||||
|
|
|
@ -30,7 +30,6 @@ from framework import users
|
|||
|
||||
from framework import basehandlers
|
||||
from internals import models
|
||||
import settings
|
||||
from internals import fetchchannels
|
||||
|
||||
SCHEDULE_CACHE_TIME = 60 * 60 # 1 hour
|
||||
|
@ -105,8 +104,3 @@ class ScheduleHandler(basehandlers.FlaskHandler):
|
|||
indent=4)
|
||||
}
|
||||
return template_data
|
||||
|
||||
|
||||
app = basehandlers.FlaskApplication([
|
||||
('/features/schedule', ScheduleHandler),
|
||||
], debug=settings.DEBUG)
|
||||
|
|
|
@ -74,9 +74,3 @@ class SettingsHandler(basehandlers.FlaskHandler):
|
|||
user_pref.notify_as_starrer = bool(new_notify)
|
||||
user_pref.put()
|
||||
return flask.redirect(flask.request.path)
|
||||
|
||||
|
||||
app = basehandlers.FlaskApplication([
|
||||
('/settings', SettingsHandler),
|
||||
('/admin/users/new', UserListHandler),
|
||||
], debug=settings.DEBUG)
|
||||
|
|
|
@ -24,6 +24,8 @@ import flask
|
|||
from internals import models
|
||||
from pages import users
|
||||
|
||||
test_app = flask.Flask(__name__)
|
||||
|
||||
|
||||
class SettingsHandlerTests(unittest.TestCase):
|
||||
|
||||
|
@ -36,7 +38,7 @@ class SettingsHandlerTests(unittest.TestCase):
|
|||
mock_gsiup.return_value = None
|
||||
mock_redirect.return_value = 'mock redirect response'
|
||||
|
||||
with users.app.test_request_context('/settings'):
|
||||
with test_app.test_request_context('/settings'):
|
||||
actual = self.handler.get_template_data()
|
||||
|
||||
mock_redirect.assert_called_once()
|
||||
|
|
|
@ -95,8 +95,6 @@ else:
|
|||
|
||||
SECRET_KEY = os.environ['DJANGO_SECRET']
|
||||
|
||||
APP_VERSION = os.environ['CURRENT_VERSION_ID'].split('.')[0]
|
||||
|
||||
RSS_FEED_LIMIT = 15
|
||||
|
||||
DEFAULT_CACHE_TIME = 60 # seconds
|
||||
|
|
Загрузка…
Ссылка в новой задаче