123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- from misago.categories.models import Category
- from misago.core.testutils import MisagoTestCase
- from misago.threads import testutils
- from misago.threads.utils import add_categories_to_items, get_thread_id_from_url
- class AddCategoriesToItemsTests(MisagoTestCase):
- def setUp(self):
- """
- Create categories tree for test cases:
- First category (created by migration)
- Category A
- + Category B
- + Subcategory C
- + Subcategory D
- Category E
- + Subcategory F
- """
- super().setUp()
- self.root = Category.objects.root_category()
- Category(
- name='Category A',
- slug='category-a',
- css_class='showing-category-a',
- ).insert_at(
- self.root,
- position='last-child',
- save=True,
- )
- Category(
- name='Category E',
- slug='category-e',
- css_class='showing-category-e',
- ).insert_at(
- self.root,
- position='last-child',
- save=True,
- )
- self.root = Category.objects.root_category()
- self.category_a = Category.objects.get(slug='category-a')
- Category(
- name='Category B',
- slug='category-b',
- css_class='showing-category-b',
- ).insert_at(
- self.category_a,
- position='last-child',
- save=True,
- )
- self.category_b = Category.objects.get(slug='category-b')
- Category(
- name='Category C',
- slug='category-c',
- css_class='showing-category-c',
- ).insert_at(
- self.category_b,
- position='last-child',
- save=True,
- )
- Category(
- name='Category D',
- slug='category-d',
- css_class='showing-category-d',
- ).insert_at(
- self.category_b,
- position='last-child',
- save=True,
- )
- self.category_c = Category.objects.get(slug='category-c')
- self.category_d = Category.objects.get(slug='category-d')
- self.category_e = Category.objects.get(slug='category-e')
- Category(
- name='Category F',
- slug='category-f',
- css_class='showing-category-f',
- ).insert_at(
- self.category_e,
- position='last-child',
- save=True,
- )
- self.clear_state()
- Category.objects.partial_rebuild(self.root.tree_id)
- self.root = Category.objects.root_category()
- self.category_a = Category.objects.get(slug='category-a')
- self.category_b = Category.objects.get(slug='category-b')
- self.category_c = Category.objects.get(slug='category-c')
- self.category_d = Category.objects.get(slug='category-d')
- self.category_e = Category.objects.get(slug='category-e')
- self.category_f = Category.objects.get(slug='category-f')
- self.categories = list(Category.objects.all_categories(include_root=True))
- def test_root_thread_from_root(self):
- """thread in root category is handled"""
- thread = testutils.post_thread(category=self.root)
- add_categories_to_items(self.root, self.categories, [thread])
- self.assertEqual(thread.category, self.root)
- def test_root_thread_from_elsewhere(self):
- """thread in root category is handled"""
- thread = testutils.post_thread(category=self.root)
- add_categories_to_items(self.category_e, self.categories, [thread])
- self.assertEqual(thread.category, self.root)
- def test_direct_child_thread_from_parent(self):
- """thread in direct child category is handled"""
- thread = testutils.post_thread(category=self.category_e)
- add_categories_to_items(self.root, self.categories, [thread])
- self.assertEqual(thread.category, self.category_e)
- def test_direct_child_thread_from_elsewhere(self):
- """thread in direct child category is handled"""
- thread = testutils.post_thread(category=self.category_e)
- add_categories_to_items(self.category_b, self.categories, [thread])
- self.assertEqual(thread.category, self.category_e)
- def test_child_thread_from_root(self):
- """thread in child category is handled"""
- thread = testutils.post_thread(category=self.category_d)
- add_categories_to_items(self.root, self.categories, [thread])
- self.assertEqual(thread.category, self.category_d)
- def test_child_thread_from_parent(self):
- """thread in child category is handled"""
- thread = testutils.post_thread(category=self.category_d)
- add_categories_to_items(self.category_a, self.categories, [thread])
- self.assertEqual(thread.category, self.category_d)
- def test_child_thread_from_category(self):
- """thread in child category is handled"""
- thread = testutils.post_thread(category=self.category_d)
- add_categories_to_items(self.category_d, self.categories, [thread])
- self.assertEqual(thread.category, self.category_d)
- def test_child_thread_from_elsewhere(self):
- """thread in child category is handled"""
- thread = testutils.post_thread(category=self.category_d)
- add_categories_to_items(self.category_f, self.categories, [thread])
- self.assertEqual(thread.category, self.category_d)
- class MockRequest(object):
- def __init__(self, scheme, host, wsgialias=''):
- self.scheme = scheme
- self.host = host
- self.path_info = '/api/threads/123/merge/'
- self.path = '{}{}'.format(wsgialias.rstrip('/'), self.path_info)
- def get_host(self):
- return self.host
- def is_secure(self):
- return self.scheme == 'https'
- class GetThreadIdFromUrlTests(MisagoTestCase):
- def test_get_thread_id_from_valid_urls(self):
- """get_thread_id_from_url extracts thread pk from valid urls"""
- TEST_CASES = [
- {
- # perfect match
- 'request': MockRequest('https', 'testforum.com', '/discuss/'),
- 'url': 'https://testforum.com/discuss/t/test-thread/123/',
- 'pk': 123,
- },
- {
- # we don't validate scheme in case site recently moved to https
- # but user still has old url's saved somewhere
- 'request': MockRequest('http', 'testforum.com', '/discuss/'),
- 'url': 'http://testforum.com/discuss/t/test-thread/432/post/12321/',
- 'pk': 432,
- },
- {
- # extract thread id from other thread urls
- 'request': MockRequest('https', 'testforum.com', '/discuss/'),
- 'url': 'http://testforum.com/discuss/t/test-thread/432/post/12321/',
- 'pk': 432,
- },
- {
- # extract thread id from thread page url
- 'request': MockRequest('http', 'testforum.com', '/discuss/'),
- 'url': 'http://testforum.com/discuss/t/test-thread/432/123/',
- 'pk': 432,
- },
- {
- # extract thread id from thread last post url with relative schema
- 'request': MockRequest('http', 'testforum.com', '/discuss/'),
- 'url': '//testforum.com/discuss/t/test-thread/18/last/',
- 'pk': 18,
- },
- {
- # extract thread id from url that lacks scheme
- 'request': MockRequest('http', 'testforum.com', ''),
- 'url': 'testforum.com/t/test-thread/12/last/',
- 'pk': 12,
- },
- {
- # extract thread id from schemaless thread last post url
- 'request': MockRequest('http', 'testforum.com', '/discuss/'),
- 'url': 'testforum.com/discuss/t/test-thread/18/last/',
- 'pk': 18,
- },
- {
- # extract thread id from url that lacks scheme and hostname
- 'request': MockRequest('http', 'testforum.com', ''),
- 'url': '/t/test-thread/13/',
- 'pk': 13,
- },
- {
- # extract thread id from url that has port name
- 'request': MockRequest('http', '127.0.0.1:8000', ''),
- 'url': 'https://127.0.0.1:8000/t/test-thread/13/',
- 'pk': 13,
- },
- {
- # extract thread id from url that isn't trimmed
- 'request': MockRequest('http', '127.0.0.1:8000', ''),
- 'url': ' /t/test-thread/13/ ',
- 'pk': 13,
- }
- ]
- for case in TEST_CASES:
- pk = get_thread_id_from_url(case['request'], case['url'])
- self.assertEqual(
- pk, case['pk'],
- 'get_thread_id_from_url for {} should return {}'.format(case['url'], case['pk'])
- )
- def test_get_thread_id_from_invalid_urls(self):
- TEST_CASES = [
- {
- # lacking wsgi alias
- 'request': MockRequest('https', 'testforum.com'),
- 'url': 'http://testforum.com/discuss/t/test-thread-123/',
- },
- {
- # invalid wsgi alias
- 'request': MockRequest('https', 'testforum.com', '/discuss/'),
- 'url': 'http://testforum.com/forum/t/test-thread-123/',
- },
- {
- # invalid hostname
- 'request': MockRequest('http', 'misago-project.org', '/discuss/'),
- 'url': 'https://testforum.com/discuss/t/test-thread-432/post/12321/',
- },
- {
- # old thread url
- 'request': MockRequest('http', 'testforum.com'),
- 'url': 'https://testforum.com/thread/bobboberson-123/',
- },
- {
- # dashed thread url
- 'request': MockRequest('http', 'testforum.com'),
- 'url': 'https://testforum.com/t/bobboberson-123/',
- },
- {
- # non-thread url
- 'request': MockRequest('http', 'testforum.com'),
- 'url': 'https://testforum.com/user/bobboberson-123/',
- },
- {
- # rubbish url
- 'request': MockRequest('http', 'testforum.com'),
- 'url': 'asdsadsasadsaSA&das8as*S(A*sa'
- },
- {
- # blank url
- 'request': MockRequest('http', 'testforum.com'),
- 'url': '/'
- },
- {
- # empty url
- 'request': MockRequest('http', 'testforum.com'),
- 'url': ''
- }
- ]
- for case in TEST_CASES:
- pk = get_thread_id_from_url(case['request'], case['url'])
- self.assertIsNone(pk, 'get_thread_id_from_url for {} should fail'.format(case['url']))
|