Phase 2: T-201 至 T-206 前台 MVP 全部实现(11 templates + CSS + 31 tests)
This commit is contained in:
+200
-17
@@ -20,6 +20,206 @@ from core.models import (
|
||||
)
|
||||
|
||||
|
||||
class PageTreeMixin:
|
||||
@classmethod
|
||||
def setUpPageTree(cls):
|
||||
cls.home = HomePage.objects.get(slug="home")
|
||||
|
||||
cls.scenario_index = ScenarioIndexPage(title="Scenarios", slug="scenarios")
|
||||
cls.home.add_child(instance=cls.scenario_index)
|
||||
cls.scenario = ScenarioPage(title="SaaS", slug="saas")
|
||||
cls.scenario_index.add_child(instance=cls.scenario)
|
||||
|
||||
cls.project_index = ProjectIndexPage(title="Projects", slug="projects")
|
||||
cls.home.add_child(instance=cls.project_index)
|
||||
|
||||
cls.article_index = ArticleIndexPage(title="Articles", slug="articles")
|
||||
cls.home.add_child(instance=cls.article_index)
|
||||
|
||||
|
||||
class ScenarioPageTests(PageTreeMixin, TestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
cls.setUpPageTree()
|
||||
cls.lang = Language.objects.create(name="Python", slug="python")
|
||||
|
||||
def test_scenario_page_with_projects(self):
|
||||
project = SkeletonProjectPage(
|
||||
title="Scenario Project",
|
||||
slug="scenario-project",
|
||||
summary="A project in this scenario",
|
||||
github_url="https://github.com/test/sproject",
|
||||
maturity="stable",
|
||||
recommended_for="Testing",
|
||||
structure_score=3, docs_score=3, tests_score=3,
|
||||
example_score=3, dependency_score=3, incremental_score=3,
|
||||
)
|
||||
self.project_index.add_child(instance=project)
|
||||
project.languages.add(self.lang)
|
||||
project.scenarios.add(self.scenario)
|
||||
project.save()
|
||||
|
||||
response = self.client.get(self.scenario.url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Scenario Project")
|
||||
|
||||
def test_empty_scenario_page(self):
|
||||
ScenarioPage.objects.create(
|
||||
title="Empty Scenario",
|
||||
slug="empty-scenario",
|
||||
path=self.scenario_index.path + "9999",
|
||||
depth=self.scenario_index.depth + 1,
|
||||
)
|
||||
response = self.client.get("/scenarios/empty-scenario/")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Nothing here yet")
|
||||
|
||||
|
||||
class ProjectFilterTests(PageTreeMixin, TestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
cls.setUpPageTree()
|
||||
cls.lang_py = Language.objects.create(name="Python", slug="python")
|
||||
cls.lang_go = Language.objects.create(name="Go", slug="go")
|
||||
cls.fw_dj = Framework.objects.create(name="Django", slug="django")
|
||||
cls.db_pg = DatabaseOption.objects.create(name="PostgreSQL", slug="postgresql")
|
||||
|
||||
cls.proj_a = SkeletonProjectPage(
|
||||
title="Django Project",
|
||||
slug="django-project",
|
||||
summary="A Django project for testing",
|
||||
github_url="https://github.com/test/django",
|
||||
maturity="stable",
|
||||
recommended_for="Testing",
|
||||
structure_score=5, docs_score=5, tests_score=5,
|
||||
example_score=5, dependency_score=5, incremental_score=5,
|
||||
)
|
||||
cls.project_index.add_child(instance=cls.proj_a)
|
||||
cls.proj_a.languages.add(cls.lang_py)
|
||||
cls.proj_a.frameworks.add(cls.fw_dj)
|
||||
cls.proj_a.databases.add(cls.db_pg)
|
||||
cls.proj_a.scenarios.add(cls.scenario)
|
||||
cls.proj_a.save()
|
||||
|
||||
cls.proj_b = SkeletonProjectPage(
|
||||
title="Go Project",
|
||||
slug="go-project",
|
||||
summary="A Go project for testing",
|
||||
github_url="https://github.com/test/go",
|
||||
maturity="experimental",
|
||||
recommended_for="Testing",
|
||||
structure_score=1, docs_score=1, tests_score=1,
|
||||
example_score=1, dependency_score=1, incremental_score=1,
|
||||
)
|
||||
cls.project_index.add_child(instance=cls.proj_b)
|
||||
cls.proj_b.languages.add(cls.lang_go)
|
||||
cls.proj_b.scenarios.add(cls.scenario)
|
||||
cls.proj_b.save()
|
||||
|
||||
def test_language_filter(self):
|
||||
resp = self.client.get("/projects/?language=python")
|
||||
self.assertContains(resp, "Django Project")
|
||||
self.assertNotContains(resp, "Go Project")
|
||||
|
||||
def test_min_score_filter(self):
|
||||
resp = self.client.get("/projects/?min_score=18")
|
||||
self.assertContains(resp, "Django Project")
|
||||
self.assertNotContains(resp, "Go Project")
|
||||
|
||||
def test_keyword_search(self):
|
||||
resp = self.client.get("/projects/?q=Django")
|
||||
self.assertContains(resp, "Django Project")
|
||||
self.assertNotContains(resp, "Go Project")
|
||||
|
||||
def test_invalid_params_ignored(self):
|
||||
resp = self.client.get("/projects/?min_score=abc&page=xyz")
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
|
||||
class SkeletonProjectDetailTests(PageTreeMixin, TestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
cls.setUpPageTree()
|
||||
cls.lang = Language.objects.create(name="Ruby", slug="ruby")
|
||||
|
||||
def test_detail_shows_scores_and_recommendation(self):
|
||||
project = SkeletonProjectPage(
|
||||
title="Detail Test",
|
||||
slug="detail-test",
|
||||
summary="Testing detail page",
|
||||
github_url="https://github.com/test/detail",
|
||||
maturity="stable",
|
||||
recommended_for="Developers who need structure",
|
||||
structure_score=4, docs_score=3, tests_score=3,
|
||||
example_score=4, dependency_score=3, incremental_score=4,
|
||||
)
|
||||
self.project_index.add_child(instance=project)
|
||||
project.languages.add(self.lang)
|
||||
project.scenarios.add(self.scenario)
|
||||
project.save()
|
||||
|
||||
resp = self.client.get(project.url)
|
||||
self.assertContains(resp, "Detail Test")
|
||||
self.assertContains(resp, "21/30")
|
||||
self.assertContains(resp, "Developers who need structure")
|
||||
|
||||
def test_sponsored_badge(self):
|
||||
project = SkeletonProjectPage(
|
||||
title="Sponsored Project",
|
||||
slug="sponsored-project",
|
||||
summary="A sponsored test",
|
||||
github_url="https://github.com/test/sponsored",
|
||||
maturity="experimental",
|
||||
recommended_for="Sponsored users",
|
||||
structure_score=2, docs_score=2, tests_score=2,
|
||||
example_score=2, dependency_score=2, incremental_score=2,
|
||||
is_sponsored=True,
|
||||
)
|
||||
self.project_index.add_child(instance=project)
|
||||
project.languages.add(self.lang)
|
||||
project.scenarios.add(self.scenario)
|
||||
project.save()
|
||||
|
||||
resp = self.client.get(project.url)
|
||||
self.assertContains(resp, "Sponsored")
|
||||
|
||||
|
||||
class ArticleDetailTests(PageTreeMixin, TestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
cls.setUpPageTree()
|
||||
cls.lang = Language.objects.create(name="Rust", slug="rust")
|
||||
|
||||
def test_article_links_to_project(self):
|
||||
project = SkeletonProjectPage(
|
||||
title="Linked Project",
|
||||
slug="linked-project",
|
||||
summary="Project linked from article",
|
||||
github_url="https://github.com/test/linked",
|
||||
maturity="stable",
|
||||
recommended_for="Testing",
|
||||
structure_score=3, docs_score=3, tests_score=3,
|
||||
example_score=3, dependency_score=3, incremental_score=3,
|
||||
)
|
||||
self.project_index.add_child(instance=project)
|
||||
project.languages.add(self.lang)
|
||||
project.scenarios.add(self.scenario)
|
||||
project.save()
|
||||
|
||||
article = ArticlePage(
|
||||
title="Review Article",
|
||||
slug="review-article",
|
||||
body="<p>About the linked project.</p>",
|
||||
)
|
||||
self.article_index.add_child(instance=article)
|
||||
article.related_projects.add(project)
|
||||
article.save()
|
||||
|
||||
resp = self.client.get(article.url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertContains(resp, "/projects/linked-project/")
|
||||
|
||||
|
||||
class LanguageTests(TestCase):
|
||||
def test_create_language(self):
|
||||
lang = Language.objects.create(name="Python", slug="python")
|
||||
@@ -64,23 +264,6 @@ class SkeletonFeatureTests(TestCase):
|
||||
SkeletonFeature.objects.create(name="Docker2", slug="docker")
|
||||
|
||||
|
||||
class PageTreeMixin:
|
||||
@classmethod
|
||||
def setUpPageTree(cls):
|
||||
cls.home = HomePage.objects.get(slug="home")
|
||||
|
||||
cls.scenario_index = ScenarioIndexPage(title="Scenarios", slug="scenarios")
|
||||
cls.home.add_child(instance=cls.scenario_index)
|
||||
cls.scenario = ScenarioPage(title="SaaS", slug="saas")
|
||||
cls.scenario_index.add_child(instance=cls.scenario)
|
||||
|
||||
cls.project_index = ProjectIndexPage(title="Projects", slug="projects")
|
||||
cls.home.add_child(instance=cls.project_index)
|
||||
|
||||
cls.article_index = ArticleIndexPage(title="Articles", slug="articles")
|
||||
cls.home.add_child(instance=cls.article_index)
|
||||
|
||||
|
||||
class SkeletonProjectPageTests(PageTreeMixin, TestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
|
||||
Reference in New Issue
Block a user