import codecs import ujson as json import unittest from wanikaniburned import app, db, User, datetime_format, parse_range from flask.ext.testing import TestCase from datetime import datetime class BaseTestCase(TestCase): def create_app(self): app.config.update( TESTING=True, SQLALCHEMY_DATABASE_URI='sqlite:///:memory:', SECRET_KEY="testkey", WTF_CSRF_ENABLED=False, PRESERVE_CONTEXT_ON_EXCEPTION=False, HASH_ROUNDS=1 ) return app def setUp(self): db.create_all() def tearDown(self): db.session.remove() db.drop_all() class TestLogin(BaseTestCase): def login(self): user = User('test', False) return self.client.post('/', data={'api_key': user.api_key}) def test_user_login(self): response = self.login() self.assertRedirects(response, '/quiz') def test_user_logout(self): response = self.login() self.assertRedirects(response, '/quiz') response = self.client.get('/logout') self.assertRedirects(response, '/') def test_homepage_without_login(self): response = self.client.get('/') self.assert200(response) self.assertTemplateUsed("welcome.html") def test_quiz_inaccessible_without_login(self): response = self.client.get('/quiz') self.assertRedirects(response, '/') def test_user_items_inaccessible_without_login(self): response = self.client.get('/user_items') self.assertRedirects(response, '/') def test_homepage_with_existing_login(self): response = self.login() # Login self.assertRedirects(response, '/quiz') response = self.client.get('/') # Try to go back to the homepage self.assertRedirects(response, '/quiz') def test_user_items_with_existing_login(self): response = self.login() # Login self.assertRedirects(response, '/quiz') response = self.client.get('/user_items') self.assert200(response) class TestFormats(unittest.TestCase): def test_custom_datetime_format(self): test_time = datetime.min output = datetime_format(test_time) self.assertEqual(output, "01 January 0001 12:00AM") def test_parse_range_empty(self): self.assertIsNone(parse_range("")) def test_parse_range_letters(self): self.assertIsNone(parse_range("ab-st,z")) def test_parse_range_single_number(self): self.assertEqual(parse_range("1"), [1]) def test_parse_range_two_with_dash(self): self.assertEqual(parse_range("1-4"), [1, 2, 3, 4]) def test_parse_range_two_with_comma(self): self.assertEqual(parse_range("1,2"), [1, 2]) def test_parse_range_dash_and_comma(self): self.assertEqual(parse_range("1,4-6"), [1, 4, 5, 6]) class TestUserItems(BaseTestCase): with codecs.open('testuserdata.json', encoding='utf-8') as input_file: user_data = json.load(input_file) user_radicals = user_data['radicals'] user_kanji = user_data['kanji'] user_vocabulary = user_data['vocabulary'] def get_user(self): user = User('test', False) user.radicals = json.dumps(self.user_radicals, ensure_ascii=False) user.kanji = json.dumps(self.user_kanji, ensure_ascii=False) user.vocabulary = json.dumps(self.user_vocabulary, ensure_ascii=False) return user def login(self, user): return self.client.post('/', data={'api_key': user.api_key}) def count_filter(self, item_list, item_type=None, level_range=list(range(0, 61))): if item_type is None: item_type = ['burned'] return sum(1 for item in item_list if item['user_specific'] and item['user_specific']['srs'] in item_type and item['level'] in level_range) def flatten_list_to_string(self, input_list): return ",".join(map(str, input_list)) def test_count_default(self): user = self.get_user() self.login(user) response = self.client.get('/user_items') response = json.loads(response.data) self.assertEqual(response['radical_count'], self.count_filter(self.user_radicals)) self.assertEqual(response['kanji_count'], self.count_filter(self.user_kanji)) self.assertEqual(response['vocabulary_count'], self.count_filter(self.user_vocabulary)) def test_filter_single_type(self): user = self.get_user() self.login(user) response = self.client.get('/user_items?item_types=radical') response = json.loads(response.data) self.assertEqual(response['radical_count'], self.count_filter(self.user_radicals)) self.assertEqual(response['kanji_count'], 0) self.assertEqual(response['vocabulary_count'], 0) def test_filter_double_type(self): user = self.get_user() self.login(user) response = self.client.get('/user_items?item_types=radical,kanji') response = json.loads(response.data) self.assertEqual(response['radical_count'], self.count_filter(self.user_radicals)) self.assertEqual(response['kanji_count'], self.count_filter(self.user_kanji)) self.assertEqual(response['vocabulary_count'], 0) def test_filter_all_type(self): user = self.get_user() self.login(user) response = self.client.get('/user_items?item_types=radical,kanji,vocab') response = json.loads(response.data) self.assertEqual(response['radical_count'], self.count_filter(self.user_radicals)) self.assertEqual(response['kanji_count'], self.count_filter(self.user_kanji)) self.assertEqual(response['vocabulary_count'], self.count_filter(self.user_vocabulary)) def test_filter_single_level(self): test_data = [1] user = self.get_user() self.login(user) response = self.client.get('/user_items?level_range=' + (self.flatten_list_to_string(test_data))) response = json.loads(response.data) self.assertEqual(response['radical_count'], self.count_filter(self.user_radicals, level_range=test_data)) self.assertEqual(response['kanji_count'], self.count_filter(self.user_kanji, level_range=test_data)) self.assertEqual(response['vocabulary_count'], self.count_filter(self.user_vocabulary, level_range=test_data)) def test_filter_multiple_levels(self): test_data = [1, 2, 4] user = self.get_user() self.login(user) response = self.client.get('/user_items?level_range=' + (self.flatten_list_to_string(test_data))) response = json.loads(response.data) self.assertEqual(response['radical_count'], self.count_filter(self.user_radicals, level_range=test_data)) self.assertEqual(response['kanji_count'], self.count_filter(self.user_kanji, level_range=test_data)) self.assertEqual(response['vocabulary_count'], self.count_filter(self.user_vocabulary, level_range=test_data)) def test_filter_single_state(self): test_data = ['enlighten'] user = self.get_user() self.login(user) response = self.client.get('/user_items?item_state=' + (self.flatten_list_to_string(test_data))) response = json.loads(response.data) self.assertEqual(response['radical_count'], self.count_filter(self.user_radicals, test_data)) self.assertEqual(response['kanji_count'], self.count_filter(self.user_kanji, test_data)) self.assertEqual(response['vocabulary_count'], self.count_filter(self.user_vocabulary, test_data)) def test_filter_multiple_state(self): test_data = ['guru', 'master', 'apprentice'] user = self.get_user() self.login(user) response = self.client.get('/user_items?item_state=' + (self.flatten_list_to_string(test_data))) response = json.loads(response.data) self.assertEqual(response['radical_count'], self.count_filter(self.user_radicals, test_data)) self.assertEqual(response['kanji_count'], self.count_filter(self.user_kanji, test_data)) self.assertEqual(response['vocabulary_count'], self.count_filter(self.user_vocabulary, test_data)) if __name__ == '__main__': unittest.main()