2021-03-23 01:33:02 +03:00
|
|
|
# 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 testing_config # Must be imported first
|
|
|
|
|
2022-02-10 22:07:45 +03:00
|
|
|
import os
|
2021-03-23 01:33:02 +03:00
|
|
|
import flask
|
|
|
|
import werkzeug
|
2022-02-10 22:07:45 +03:00
|
|
|
import html5lib
|
2022-10-19 20:51:39 +03:00
|
|
|
import settings
|
2021-03-23 01:33:02 +03:00
|
|
|
|
2022-08-24 02:00:02 +03:00
|
|
|
from internals import core_enums
|
|
|
|
from internals import core_models
|
2022-08-18 04:14:19 +03:00
|
|
|
from internals import user_models
|
2021-03-23 01:33:02 +03:00
|
|
|
from pages import featurelist
|
2022-09-14 20:07:32 +03:00
|
|
|
from framework import rediscache
|
2021-03-23 01:33:02 +03:00
|
|
|
|
2022-10-19 20:51:39 +03:00
|
|
|
test_app = flask.Flask(__name__,
|
|
|
|
template_folder=settings.get_flask_template_path())
|
2021-09-23 23:01:43 +03:00
|
|
|
|
2022-10-19 17:14:52 +03:00
|
|
|
# Load testdata to be used across all of the CustomTestCases
|
|
|
|
TESTDATA = testing_config.Testdata(__file__)
|
2021-03-23 01:33:02 +03:00
|
|
|
|
2021-06-29 05:05:04 +03:00
|
|
|
class TestWithFeature(testing_config.CustomTestCase):
|
2021-03-23 01:33:02 +03:00
|
|
|
|
|
|
|
REQUEST_PATH_FORMAT = 'subclasses fill this in'
|
|
|
|
HANDLER_CLASS = 'subclasses fill this in'
|
|
|
|
|
|
|
|
def setUp(self):
|
2022-08-18 04:14:19 +03:00
|
|
|
self.app_user = user_models.AppUser(email='registered@example.com')
|
2022-07-14 00:31:27 +03:00
|
|
|
self.app_user.put()
|
|
|
|
|
2022-08-18 04:14:19 +03:00
|
|
|
self.app_admin = user_models.AppUser(email='admin@example.com')
|
2022-07-14 00:31:27 +03:00
|
|
|
self.app_admin.is_admin = True
|
|
|
|
self.app_admin.put()
|
|
|
|
|
2022-08-24 02:00:02 +03:00
|
|
|
self.feature_1 = core_models.Feature(
|
2022-07-14 00:31:27 +03:00
|
|
|
name='feature one', summary='detailed sum', owner=['owner@example.com'],
|
2022-10-10 20:43:40 +03:00
|
|
|
category=1, intent_stage=core_enums.INTENT_IMPLEMENT)
|
2021-03-23 01:33:02 +03:00
|
|
|
self.feature_1.put()
|
2021-06-17 23:47:02 +03:00
|
|
|
self.feature_id = self.feature_1.key.integer_id()
|
2021-03-23 01:33:02 +03:00
|
|
|
|
|
|
|
self.request_path = self.REQUEST_PATH_FORMAT % {
|
|
|
|
'feature_id': self.feature_id,
|
|
|
|
}
|
|
|
|
self.handler = self.HANDLER_CLASS()
|
|
|
|
|
|
|
|
def tearDown(self):
|
2021-06-17 23:47:02 +03:00
|
|
|
self.feature_1.key.delete()
|
2022-07-14 00:31:27 +03:00
|
|
|
self.app_user.delete()
|
|
|
|
self.app_admin.delete()
|
2022-09-14 20:07:32 +03:00
|
|
|
rediscache.flushall()
|
2021-03-23 01:33:02 +03:00
|
|
|
|
|
|
|
|
|
|
|
class FeaturesJsonHandlerTest(TestWithFeature):
|
|
|
|
|
|
|
|
REQUEST_PATH_FORMAT = '/features.json'
|
|
|
|
HANDLER_CLASS = featurelist.FeaturesJsonHandler
|
|
|
|
|
|
|
|
def test_get_template_data(self):
|
|
|
|
"""User can get a JSON feed of all features."""
|
2021-09-14 23:23:16 +03:00
|
|
|
testing_config.sign_in('user@example.com', 111)
|
2021-09-23 23:01:43 +03:00
|
|
|
with test_app.test_request_context(self.request_path):
|
2021-03-23 01:33:02 +03:00
|
|
|
json_data = self.handler.get_template_data()
|
|
|
|
|
|
|
|
self.assertEqual(1, len(json_data))
|
|
|
|
self.assertEqual('feature one', json_data[0]['name'])
|
2021-04-24 00:12:07 +03:00
|
|
|
|
|
|
|
def test_get_template_data__unlisted_no_perms(self):
|
|
|
|
"""JSON feed does not include unlisted features for users who can't edit."""
|
|
|
|
self.feature_1.unlisted = True
|
|
|
|
self.feature_1.put()
|
|
|
|
|
|
|
|
testing_config.sign_out()
|
2021-09-23 23:01:43 +03:00
|
|
|
with test_app.test_request_context(self.request_path):
|
2021-04-24 00:12:07 +03:00
|
|
|
json_data = self.handler.get_template_data()
|
|
|
|
self.assertEqual(0, len(json_data))
|
|
|
|
|
|
|
|
testing_config.sign_in('user@example.com', 111)
|
2021-09-23 23:01:43 +03:00
|
|
|
with test_app.test_request_context(self.request_path):
|
2021-04-24 00:12:07 +03:00
|
|
|
json_data = self.handler.get_template_data()
|
|
|
|
self.assertEqual(0, len(json_data))
|
|
|
|
|
|
|
|
def test_get_template_data__unlisted_can_edit(self):
|
2022-07-14 00:31:27 +03:00
|
|
|
"""JSON feed includes unlisted features for site editors and admins."""
|
2021-04-24 00:12:07 +03:00
|
|
|
self.feature_1.unlisted = True
|
|
|
|
self.feature_1.put()
|
|
|
|
|
2022-07-14 00:31:27 +03:00
|
|
|
testing_config.sign_in('admin@example.com', 111)
|
2021-09-23 23:01:43 +03:00
|
|
|
with test_app.test_request_context(self.request_path):
|
2021-04-24 00:12:07 +03:00
|
|
|
json_data = self.handler.get_template_data()
|
|
|
|
self.assertEqual(1, len(json_data))
|
|
|
|
self.assertEqual('feature one', json_data[0]['name'])
|
2021-03-23 01:33:02 +03:00
|
|
|
|
|
|
|
|
|
|
|
class FeatureListHandlerTest(TestWithFeature):
|
|
|
|
|
|
|
|
REQUEST_PATH_FORMAT = '/features'
|
|
|
|
HANDLER_CLASS = featurelist.FeatureListHandler
|
|
|
|
|
|
|
|
def test_get_template_data(self):
|
|
|
|
"""User can get a feature list page."""
|
2021-09-23 23:01:43 +03:00
|
|
|
with test_app.test_request_context(self.request_path):
|
2021-03-23 01:33:02 +03:00
|
|
|
template_data = self.handler.get_template_data()
|
|
|
|
|
|
|
|
self.assertIn('IMPLEMENTATION_STATUSES', template_data)
|
|
|
|
|
|
|
|
|
2022-02-10 22:07:45 +03:00
|
|
|
class FeatureListTemplateTest(TestWithFeature):
|
|
|
|
|
|
|
|
HANDLER_CLASS = featurelist.FeatureListHandler
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(FeatureListTemplateTest, self).setUp()
|
|
|
|
with test_app.test_request_context(self.request_path):
|
|
|
|
self.template_data = self.handler.get_template_data(
|
|
|
|
feature_id=self.feature_id)
|
|
|
|
|
2022-10-19 17:14:52 +03:00
|
|
|
testing_config.sign_in('admin@example.com', 111)
|
|
|
|
|
2022-02-10 22:07:45 +03:00
|
|
|
self.template_data.update(self.handler.get_common_data())
|
|
|
|
self.template_data['nonce'] = 'fake nonce'
|
2022-10-19 17:14:52 +03:00
|
|
|
self.template_data['xsrf_token'] = ''
|
|
|
|
self.template_data['xsrf_token_expires'] = 0
|
2022-02-10 22:07:45 +03:00
|
|
|
template_path = self.handler.get_template_path(self.template_data)
|
|
|
|
self.full_template_path = os.path.join(template_path)
|
2022-10-19 17:14:52 +03:00
|
|
|
self.maxDiff = None
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
testing_config.sign_out()
|
2022-08-18 04:14:19 +03:00
|
|
|
|
2022-02-10 22:07:45 +03:00
|
|
|
def test_html_rendering(self):
|
|
|
|
"""We can render the template with valid html."""
|
2022-10-19 20:51:39 +03:00
|
|
|
with test_app.app_context():
|
|
|
|
template_text = self.handler.render(
|
|
|
|
self.template_data, self.full_template_path)
|
2022-02-10 22:07:45 +03:00
|
|
|
parser = html5lib.HTMLParser(strict=True)
|
|
|
|
document = parser.parse(template_text)
|
2022-10-19 17:14:52 +03:00
|
|
|
# TESTDATA.make_golden(template_text, 'test_html_rendering.html')
|
|
|
|
self.assertMultiLineEqual(
|
|
|
|
TESTDATA['test_html_rendering.html'], template_text)
|
2022-02-10 22:07:45 +03:00
|
|
|
|
|
|
|
|
2021-03-23 01:33:02 +03:00
|
|
|
class FeatureListXMLHandlerTest(TestWithFeature):
|
|
|
|
|
|
|
|
REQUEST_PATH_FORMAT = '/features.xml'
|
|
|
|
HANDLER_CLASS = featurelist.FeatureListXMLHandler
|
|
|
|
|
|
|
|
def test_get_template_data__no_filters(self):
|
|
|
|
"""User can get an XML feed of all features."""
|
2021-09-23 23:01:43 +03:00
|
|
|
with test_app.test_request_context(self.request_path):
|
2021-03-23 01:33:02 +03:00
|
|
|
actual_text, actual_headers = self.handler.get_template_data()
|
|
|
|
|
|
|
|
self.assertTrue(actual_text.startswith('<?xml'))
|
|
|
|
self.assertIn('feature one', actual_text)
|
|
|
|
self.assertIn('detailed sum', actual_text)
|
|
|
|
self.assertIn(str(self.feature_id), actual_text)
|
|
|
|
|
|
|
|
self.assertIn('atom+xml', actual_headers['Content-Type'])
|
|
|
|
|
|
|
|
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'
|
2021-09-23 23:01:43 +03:00
|
|
|
with test_app.test_request_context(request_path):
|
2021-03-23 01:33:02 +03:00
|
|
|
actual_text, actual_headers = self.handler.get_template_data()
|
|
|
|
|
|
|
|
# It is an XML feed
|
|
|
|
self.assertTrue(actual_text.startswith('<?xml'))
|
|
|
|
self.assertIn('atom+xml', actual_headers['Content-Type'])
|
|
|
|
self.assertIn('Features', actual_text)
|
|
|
|
|
|
|
|
# feature_1 is in the list
|
|
|
|
self.assertIn('feature one', actual_text)
|
|
|
|
self.assertIn('detailed sum', actual_text)
|
|
|
|
self.assertIn(str(self.feature_id), actual_text)
|
|
|
|
|
|
|
|
|
|
|
|
request_path = self.request_path + '?category=css'
|
2021-09-23 23:01:43 +03:00
|
|
|
with test_app.test_request_context(request_path):
|
2021-03-23 01:33:02 +03:00
|
|
|
actual_text, actual_headers = self.handler.get_template_data()
|
|
|
|
|
|
|
|
self.assertTrue(actual_text.startswith('<?xml'))
|
2021-09-23 23:01:43 +03:00
|
|
|
self.assertNotIn('feature one', actual_text)
|