|
| 1 | +import json |
| 2 | + |
1 | 3 | import pytest |
2 | 4 |
|
3 | 5 | from tiklocal.app import create_app |
@@ -72,3 +74,115 @@ def test_mix_feed_falls_back_to_videos_when_no_images(tmp_path, monkeypatch): |
72 | 74 | items = data["items"] |
73 | 75 | assert len(items) > 0 |
74 | 76 | assert all(item["type"] == "video" for item in items) |
| 77 | + |
| 78 | + |
| 79 | +def test_mix_feed_can_insert_theme_strip_for_recent_downloads_and_favorites(tmp_path, monkeypatch): |
| 80 | + media_root = tmp_path / "media" |
| 81 | + media_root.mkdir(parents=True, exist_ok=True) |
| 82 | + for name in ("v1.mp4", "v2.mp4", "i1.jpg", "i2.png", "i3.jpg"): |
| 83 | + (media_root / name).write_bytes(b"00") |
| 84 | + |
| 85 | + (media_root / "favorite.json").write_text( |
| 86 | + json.dumps(["i1.jpg", "i2.png", "v1.mp4"]), |
| 87 | + encoding="utf-8", |
| 88 | + ) |
| 89 | + |
| 90 | + data_root = tmp_path / "tiklocal-data" |
| 91 | + data_root.mkdir(parents=True, exist_ok=True) |
| 92 | + (data_root / "download_jobs.json").write_text( |
| 93 | + json.dumps([ |
| 94 | + { |
| 95 | + "id": "job-1", |
| 96 | + "status": "success", |
| 97 | + "created_at": "2026-03-14T10:00:00Z", |
| 98 | + "output_files_rel": ["i3.jpg", "v2.mp4", "i2.png"], |
| 99 | + } |
| 100 | + ]), |
| 101 | + encoding="utf-8", |
| 102 | + ) |
| 103 | + |
| 104 | + monkeypatch.setenv("MEDIA_ROOT", str(media_root)) |
| 105 | + monkeypatch.setenv("TIKLOCAL_INSTANCE", str(data_root)) |
| 106 | + |
| 107 | + app = create_app({"TESTING": True, "MEDIA_ROOT": media_root}) |
| 108 | + test_client = app.test_client() |
| 109 | + |
| 110 | + res = test_client.get("/api/feed/mix?page=1&size=24&seed=theme-seed") |
| 111 | + assert res.status_code == 200 |
| 112 | + data = res.get_json() |
| 113 | + |
| 114 | + items = data["items"] |
| 115 | + strip = next((item for item in items if item.get("type") == "theme_strip"), None) |
| 116 | + assert strip is not None |
| 117 | + assert strip["name"] in {"theme:recent-downloads", "theme:favorite-picks"} |
| 118 | + assert strip["title"] |
| 119 | + assert strip["target_url"] in {"/favorite", "/library"} |
| 120 | + assert strip["target_label"] |
| 121 | + assert len(strip["items"]) >= 3 |
| 122 | + for child in strip["items"]: |
| 123 | + assert child["type"] in {"video", "image"} |
| 124 | + assert child["name"] |
| 125 | + assert child["media_url"] |
| 126 | + assert child["thumb_url"] |
| 127 | + assert child["detail_url"] |
| 128 | + assert child["focus_url"] |
| 129 | + |
| 130 | + |
| 131 | +def test_mix_feed_prefers_original_post_group_when_source_has_multiple_media(tmp_path, monkeypatch): |
| 132 | + media_root = tmp_path / "media" |
| 133 | + media_root.mkdir(parents=True, exist_ok=True) |
| 134 | + for name in ("set-1.jpg", "set-2.jpg", "solo.mp4", "fallback.jpg"): |
| 135 | + (media_root / name).write_bytes(b"00") |
| 136 | + |
| 137 | + data_root = tmp_path / "tiklocal-data" |
| 138 | + data_root.mkdir(parents=True, exist_ok=True) |
| 139 | + (data_root / "download_sources.json").write_text( |
| 140 | + json.dumps( |
| 141 | + { |
| 142 | + "version": 1, |
| 143 | + "updated_at": "2026-03-14T10:30:00Z", |
| 144 | + "items": { |
| 145 | + "set-1.jpg": { |
| 146 | + "source_url_raw": "https://x.com/demo/status/100", |
| 147 | + "source_url_display": "https://x.com/demo/status/100", |
| 148 | + "source_domain": "x.com", |
| 149 | + "job_id": "job-group", |
| 150 | + "created_at": "2026-03-14T10:00:00Z", |
| 151 | + }, |
| 152 | + "set-2.jpg": { |
| 153 | + "source_url_raw": "https://x.com/demo/status/100", |
| 154 | + "source_url_display": "https://x.com/demo/status/100", |
| 155 | + "source_domain": "x.com", |
| 156 | + "job_id": "job-group", |
| 157 | + "created_at": "2026-03-14T10:00:00Z", |
| 158 | + }, |
| 159 | + "solo.mp4": { |
| 160 | + "source_url_raw": "https://x.com/demo/status/101", |
| 161 | + "source_url_display": "https://x.com/demo/status/101", |
| 162 | + "source_domain": "x.com", |
| 163 | + "job_id": "job-solo", |
| 164 | + "created_at": "2026-03-14T09:00:00Z", |
| 165 | + }, |
| 166 | + }, |
| 167 | + } |
| 168 | + ), |
| 169 | + encoding="utf-8", |
| 170 | + ) |
| 171 | + |
| 172 | + monkeypatch.setenv("MEDIA_ROOT", str(media_root)) |
| 173 | + monkeypatch.setenv("TIKLOCAL_INSTANCE", str(data_root)) |
| 174 | + |
| 175 | + app = create_app({"TESTING": True, "MEDIA_ROOT": media_root}) |
| 176 | + test_client = app.test_client() |
| 177 | + |
| 178 | + res = test_client.get("/api/feed/mix?page=1&size=24&seed=group-seed") |
| 179 | + assert res.status_code == 200 |
| 180 | + data = res.get_json() |
| 181 | + |
| 182 | + group = next((item for item in data["items"] if item.get("type") == "image_group"), None) |
| 183 | + assert group is not None |
| 184 | + assert group["title"] == "原始图集" |
| 185 | + names = [child["name"] for child in group["items"]] |
| 186 | + assert "set-1.jpg" in names |
| 187 | + assert "set-2.jpg" in names |
| 188 | + assert all(child["media_url"] for child in group["items"]) |
0 commit comments