Coverage for tests/endpoints/publisher/tests_listing.py: 100%
112 statements
« prev ^ index » next coverage.py v7.10.5, created at 2025-08-26 22:06 +0000
« prev ^ index » next coverage.py v7.10.5, created at 2025-08-26 22:06 +0000
1from unittest.mock import patch
2from tests.endpoints.endpoint_testing import TestEndpoints
5class TestGetListingData(TestEndpoints):
6 @patch("webapp.endpoints.publisher.listing.helpers.get_yaml")
7 @patch("webapp.endpoints.publisher.listing.helpers.get_licenses")
8 @patch("webapp.endpoints.publisher.listing.logic.filter_categories")
9 @patch(
10 "webapp.endpoints.publisher.listing.logic."
11 "replace_reserved_categories_key"
12 )
13 @patch("webapp.endpoints.publisher.listing.logic.categorise_media")
14 @patch("webapp.endpoints.publisher.listing.get_categories")
15 @patch("webapp.endpoints.publisher.listing.device_gateway")
16 @patch("webapp.endpoints.publisher.listing.dashboard")
17 def test_get_listing_data_success(
18 self,
19 mock_dashboard,
20 mock_device_gateway,
21 mock_get_categories,
22 mock_categorise_media,
23 mock_replace_reserved_categories_key,
24 mock_filter_categories,
25 mock_get_licenses,
26 mock_get_yaml,
27 ):
28 # Mock snap details from dashboard
29 mock_snap_details = {
30 "title": "Test Snap",
31 "summary": "A test snap for testing",
32 "description": (
33 "This is a test snap used for unit testing purposes"
34 ),
35 "snap_id": "test-snap-id-123",
36 "public_metrics_enabled": True,
37 "public_metrics_blacklist": ["install_size"],
38 "media": [
39 {"type": "icon", "url": "https://example.com/icon.png"},
40 {
41 "type": "screenshot",
42 "url": "https://example.com/screenshot.png",
43 },
44 ],
45 "links": {
46 "website": ["https://example.com", "https://secondary.com"],
47 "contact": ["mailto:contact@example.com"],
48 "source": ["https://github.com/example/repo"],
49 },
50 "license": "MIT",
51 "categories": [{"name": "productivity"}, {"name": "utilities"}],
52 "video_urls": ["https://example.com/video.mp4"],
53 "update_metadata_on_release": True,
54 }
55 mock_dashboard.get_snap_info.return_value = mock_snap_details
57 # Mock device gateway categories
58 mock_device_gateway.get_categories.return_value = [
59 {"name": "productivity", "slug": "productivity"},
60 {"name": "utilities", "slug": "utilities"},
61 ]
63 # Mock get_categories function
64 mock_get_categories.return_value = [
65 {"name": "productivity", "slug": "productivity"},
66 {"name": "utilities", "slug": "utilities"},
67 ]
69 # Mock media categorization
70 mock_categorise_media.return_value = (
71 ["https://example.com/icon.png"], # icon_urls
72 ["https://example.com/screenshot.png"], # screenshot_urls
73 [], # banner_urls
74 )
76 # Mock category processing
77 mock_replace_reserved_categories_key.return_value = {
78 "categories": [{"name": "productivity"}, {"name": "utilities"}]
79 }
80 mock_filter_categories.return_value = {
81 "categories": [{"name": "productivity"}, {"name": "utilities"}]
82 }
84 # Mock licenses
85 mock_get_licenses.return_value = [
86 {"licenseId": "MIT", "name": "MIT License"},
87 {"licenseId": "Apache-2.0", "name": "Apache License 2.0"},
88 ]
90 # Mock YAML tour steps
91 mock_get_yaml.return_value = [
92 {"title": "Welcome", "content": "Welcome to the tour"}
93 ]
95 # Make the request
96 response = self.client.get("/api/test-snap/listing")
97 data = response.json
99 # Assert response structure
100 self.assertEqual(response.status_code, 200)
101 self.assertTrue(data["success"])
102 self.assertEqual(data["message"], "")
103 self.assertIn("data", data)
105 # Assert specific data fields
106 context = data["data"]
107 self.assertEqual(context["title"], "Test Snap")
108 self.assertEqual(context["summary"], "A test snap for testing")
109 self.assertEqual(context["snap_id"], "test-snap-id-123")
110 self.assertTrue(context["public_metrics_enabled"])
111 self.assertEqual(context["public_metrics_blacklist"], ["install_size"])
112 self.assertEqual(context["license"], "MIT")
113 self.assertEqual(context["license_type"], "simple")
114 self.assertEqual(context["primary_website"], "https://example.com")
115 self.assertEqual(context["primary_category"], "productivity")
116 self.assertEqual(context["secondary_category"], "utilities")
117 self.assertEqual(context["icon_url"], "https://example.com/icon.png")
118 self.assertEqual(
119 context["video_urls"], "https://example.com/video.mp4"
120 )
121 self.assertTrue(context["update_metadata_on_release"])
123 # Verify mocks were called correctly
124 mock_dashboard.get_snap_info.assert_called_once()
125 mock_device_gateway.get_categories.assert_called_once()
126 mock_categorise_media.assert_called_once()
128 @patch("webapp.endpoints.publisher.listing.helpers.get_yaml")
129 @patch("webapp.endpoints.publisher.listing.helpers.get_licenses")
130 @patch("webapp.endpoints.publisher.listing.logic.filter_categories")
131 @patch(
132 "webapp.endpoints.publisher.listing.logic."
133 "replace_reserved_categories_key"
134 )
135 @patch("webapp.endpoints.publisher.listing.logic.categorise_media")
136 @patch("webapp.endpoints.publisher.listing.get_categories")
137 @patch("webapp.endpoints.publisher.listing.device_gateway")
138 @patch("webapp.endpoints.publisher.listing.dashboard")
139 def test_get_listing_data_minimal_snap_details(
140 self,
141 mock_dashboard,
142 mock_device_gateway,
143 mock_get_categories,
144 mock_categorise_media,
145 mock_replace_reserved_categories_key,
146 mock_filter_categories,
147 mock_get_licenses,
148 mock_get_yaml,
149 ):
150 # Mock minimal snap details
151 mock_snap_details = {
152 "title": "Minimal Snap",
153 "summary": "Minimal test snap",
154 "description": "A minimal snap for testing edge cases",
155 "snap_id": "minimal-snap-id",
156 "public_metrics_enabled": False,
157 "public_metrics_blacklist": [],
158 "media": [],
159 "links": {},
160 "license": "Proprietary",
161 "categories": [],
162 "video_urls": [],
163 "update_metadata_on_release": False,
164 }
165 mock_dashboard.get_snap_info.return_value = mock_snap_details
167 # Mock other dependencies with minimal data
168 mock_device_gateway.get_categories.return_value = []
169 mock_get_categories.return_value = []
170 mock_categorise_media.return_value = ([], [], [])
171 mock_replace_reserved_categories_key.return_value = {"categories": []}
172 mock_filter_categories.return_value = {"categories": []}
173 mock_get_licenses.return_value = []
174 mock_get_yaml.return_value = []
176 # Make the request
177 response = self.client.get("/api/minimal-snap/listing")
178 data = response.json
180 # Assert response structure
181 self.assertEqual(response.status_code, 200)
182 self.assertTrue(data["success"])
184 # Assert minimal data handling
185 context = data["data"]
186 self.assertEqual(context["title"], "Minimal Snap")
187 self.assertEqual(context["primary_website"], "")
188 self.assertEqual(context["websites"], [])
189 self.assertEqual(context["primary_category"], "")
190 self.assertEqual(context["secondary_category"], "")
191 self.assertIsNone(context["icon_url"])
192 self.assertEqual(context["screenshot_urls"], [])
193 self.assertIsNone(context["video_urls"])
196class TestPostListingData(TestEndpoints):
197 @patch("webapp.endpoints.publisher.listing.dashboard")
198 @patch("webapp.endpoints.publisher.listing.logic.filter_changes_data")
199 def test_post_listing_data_success_no_changes(
200 self,
201 mock_filter_changes_data,
202 mock_dashboard,
203 ):
204 """Test POST with no changes returns success"""
205 # Make the request with no changes
206 response = self.client.post("/api/test-snap/listing")
207 data = response.json
209 # Assert response
210 self.assertEqual(response.status_code, 200)
211 self.assertTrue(data["success"])
213 # Verify no API calls were made since there were no changes
214 mock_dashboard.snap_screenshots.assert_not_called()
215 mock_dashboard.snap_metadata.assert_not_called()
217 @patch("webapp.endpoints.publisher.listing.dashboard")
218 @patch("webapp.endpoints.publisher.listing.logic.filter_changes_data")
219 @patch(
220 "webapp.endpoints.publisher.listing.logic.remove_invalid_characters"
221 )
222 def test_post_listing_data_success_with_metadata_changes(
223 self,
224 mock_remove_invalid_characters,
225 mock_filter_changes_data,
226 mock_dashboard,
227 ):
228 """Test POST with metadata changes (title, description, etc.)"""
229 # Mock the filter_changes_data to return some changes
230 mock_filter_changes_data.return_value = {
231 "title": "Updated Title",
232 "description": "Updated description with some content",
233 "summary": "Updated summary",
234 }
236 # Mock character removal
237 mock_remove_invalid_characters.return_value = (
238 "Updated description with some content"
239 )
241 # Prepare form data
242 form_data = {
243 "changes": (
244 '{"title": "Updated Title", '
245 '"description": "Updated description"}'
246 ),
247 "snap_id": "test-snap-id-123",
248 }
250 # Make the request
251 response = self.client.post("/api/test-snap/listing", data=form_data)
252 data = response.json
254 # Assert response
255 self.assertEqual(response.status_code, 200)
256 self.assertTrue(data["success"])
258 # Verify snap_metadata was called with the filtered data
259 mock_dashboard.snap_metadata.assert_called_once()
260 call_args = mock_dashboard.snap_metadata.call_args
261 self.assertEqual(call_args[0][1], "test-snap-id-123") # snap_id
263 # Verify description was processed for invalid characters
264 mock_remove_invalid_characters.assert_called_once_with(
265 "Updated description with some content"
266 )
268 @patch("webapp.endpoints.publisher.listing.dashboard")
269 @patch("webapp.endpoints.publisher.listing.logic.build_changed_images")
270 def test_post_listing_data_success_with_image_changes(
271 self,
272 mock_build_changed_images,
273 mock_dashboard,
274 ):
275 """Test POST with image changes (icon, screenshots, banner)"""
276 # Mock existing screenshots
277 mock_dashboard.snap_screenshots.side_effect = [
278 # First call for current screenshots
279 [{"type": "screenshot", "url": "existing.png"}],
280 None, # Second call for updating screenshots
281 ]
283 # Mock build_changed_images
284 mock_build_changed_images.return_value = (
285 [{"type": "icon", "url": "new-icon.png"}], # images_json
286 [], # images_files
287 )
289 # Prepare form data with image changes
290 form_data = {
291 "changes": '{"images": {"icon": "new-icon.png"}}',
292 "snap_id": "test-snap-id-456",
293 }
295 # Make the request
296 response = self.client.post("/api/test-snap/listing", data=form_data)
297 data = response.json
299 # Assert response
300 self.assertEqual(response.status_code, 200)
301 self.assertTrue(data["success"])
303 # Verify screenshots were fetched and updated
304 self.assertEqual(mock_dashboard.snap_screenshots.call_count, 2)
306 # Verify build_changed_images was called
307 mock_build_changed_images.assert_called_once()