Files
chunyu_project/search/tests/test_search_c07.py
T
chunyu 1e95db0bda fix(C-07):搜索边界收口+结果跳转死链修复
q超长截断100字符、page/page_size健壮解析、types白名单;文章/工具/课程/接口结果URL对齐前端现行路由(/post、/utility、/course-learn、/open-api-detail)。
2026-09-15 15:20:19 +08:00

91 lines
3.5 KiB
Python

"""C-07 全站统一搜索回归:多模块聚合/类型筛选/分页/异常输入健壮性/结果跳转死链。"""
from django.test import TestCase
from rest_framework.test import APIClient
from article.models import Article
from tool.models import Tool
from learn.models import Course
from apidirectory.models import ApiItem
from user.models import FUser
KW = 'c07searchkey'
class UnifiedSearchTest(TestCase):
def setUp(self):
self.client = APIClient()
self.u = FUser.objects.create_user(username='c07u', password='x12345678')
self.art = Article.objects.create(
title=f'{KW}文章', content='x' * 500, author=self.u, status='published')
self.tool = Tool.objects.create(
name=f'{KW}工具', description='desc', url_path='/utility/c07-tool')
self.course = Course.objects.create(
title=f'{KW}课程', description='desc', author=self.u, status='published')
self.api = ApiItem.objects.create(
name=f'{KW}接口', description='desc', url_path='/api/c07',
method='GET', is_enabled=True)
def _get(self, **params):
r = self.client.get('/search/', params)
self.assertEqual(r.status_code, 200)
body = r.json()
self.assertEqual(body.get('code'), 10000)
return body['data']
def test_multi_module_hit(self):
data = self._get(q=KW)
titles = [x['title'] for x in data['results']]
self.assertIn(f'{KW}文章', titles)
self.assertIn(f'{KW}工具', titles)
self.assertIn(f'{KW}课程', titles)
self.assertIn(f'{KW}接口', titles)
self.assertGreaterEqual(data['total'], 4)
def test_type_filter_article(self):
data = self._get(q=KW, type='article')
self.assertTrue(data['results'])
self.assertTrue(all(x['type'] == '文章' for x in data['results']))
def test_type_filter_tool(self):
data = self._get(q=KW, type='tool')
self.assertTrue(data['results'])
self.assertTrue(all(x['type'] == '工具' for x in data['results']))
def test_result_urls_are_live_routes(self):
data = self._get(q=KW)
by_type = {x['type']: x for x in data['results']}
self.assertTrue(by_type['文章']['url'].startswith('/post/'))
self.assertEqual(by_type['工具']['url'], '/utility/c07-tool')
self.assertTrue(by_type['课程']['url'].startswith('/course-learn?id='))
self.assertTrue(by_type['API']['url'].startswith('/open-api-detail/'))
def test_pagination(self):
data = self._get(q=KW, page=1, page_size=2)
self.assertEqual(len(data['results']), 2)
data2 = self._get(q=KW, page=2, page_size=2)
self.assertTrue(data2['results'])
def test_empty_q_graceful(self):
data = self._get(q='')
self.assertEqual(data['results'], [])
self.assertEqual(data['total'], 0)
def test_long_q_truncated_no_500(self):
data = self._get(q='x' * 5000)
self.assertIn('results', data)
def test_special_chars_no_500(self):
for bad in ['%_%', "a'b\"c", '<script>', '*/--', '你好*?']:
data = self._get(q=bad)
self.assertIn('results', data)
def test_invalid_type_falls_back_all(self):
data = self._get(q=KW, type='not_a_type')
self.assertGreaterEqual(data['total'], 4)
def test_invalid_page_params_no_500(self):
data = self._get(q=KW, page='abc', page_size='xyz')
self.assertIn('results', data)
data = self._get(q=KW, page=-5, page_size=9999)
self.assertIn('results', data)