From 83edea0fab19b8e70ee71c8386af5474e6a532b9 Mon Sep 17 00:00:00 2001 From: Chatewgne Date: Mon, 9 Sep 2024 15:28:27 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20[BUG]=20Fix=20Aggregator=20does?= =?UTF-8?q?=20not=20retrieve=20unpublished=20Tour=20Steps=20(refs=20#3569)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/changelog.rst | 1 + geotrek/common/tests/test_parsers.py | 56 +++- geotrek/trekking/parsers.py | 17 +- .../data/geotrek_parser_v2/trek_children.json | 5 +- .../trek_children_do_not_exist.json | 6 +- .../geotrek_parser_v2/trek_no_children.json | 27 ++ .../geotrek_parser_v2/trek_not_found.json | 3 + .../trek_published_step.json | 209 ++++++++++++ .../trek_unpublished_step.json | 308 ++++++++++++++++++ .../trek_wrong_children.json | 22 -- geotrek/trekking/tests/test_parsers.py | 79 +++-- 11 files changed, 658 insertions(+), 75 deletions(-) create mode 100644 geotrek/trekking/tests/data/geotrek_parser_v2/trek_no_children.json create mode 100644 geotrek/trekking/tests/data/geotrek_parser_v2/trek_not_found.json create mode 100644 geotrek/trekking/tests/data/geotrek_parser_v2/trek_published_step.json create mode 100644 geotrek/trekking/tests/data/geotrek_parser_v2/trek_unpublished_step.json delete mode 100644 geotrek/trekking/tests/data/geotrek_parser_v2/trek_wrong_children.json diff --git a/docs/changelog.rst b/docs/changelog.rst index 05482ea765..d722ccb190 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -22,6 +22,7 @@ CHANGELOG - ApidaeTrekParser duration import is fixed for multiple-days treks - Apidae tourism parser now handles missing contact properties - ApidaeTrekParser now handles missing source website +- Fix Aggregator does not retrieve unpublished Tour Steps (#3569)" **Documentation** diff --git a/geotrek/common/tests/test_parsers.py b/geotrek/common/tests/test_parsers.py index 9881ad0670..c255ec2c11 100644 --- a/geotrek/common/tests/test_parsers.py +++ b/geotrek/common/tests/test_parsers.py @@ -668,7 +668,7 @@ class GeotrekAggregatorTestParser(GeotrekAggregatorParser): pass -class GeotrekParserTest(TestCase): +class GeotrekParserTest(GeotrekParserTestMixin, TestCase): def setUp(self, *args, **kwargs): self.filetype = FileType.objects.create(type="Photographie") @@ -676,16 +676,27 @@ def test_improperly_configurated_categories(self): with self.assertRaisesRegex(ImproperlyConfigured, 'foo_field is not configured in categories_keys_api_v2'): call_command('import', 'geotrek.common.tests.test_parsers.GeotrekTrekTestParser', verbosity=2) - def mock_json(self): - filename = os.path.join('geotrek', 'common', 'tests', 'data', 'geotrek_parser_v2', 'treks.json') - with open(filename, 'r') as f: - return json.load(f) - @mock.patch('requests.get') - def test_delete_according_to_provider(self, mocked_get): + @mock.patch('requests.head') + def test_delete_according_to_provider(self, mocked_head, mocked_get): + self.mock_time = 0 + self.mock_json_order = [ + ('common', 'treks.json'), + ('common', 'treks.json'), + ('trekking', 'trek_no_children.json'), + ('common', 'treks.json'), + ('common', 'treks.json'), + ('trekking', 'trek_no_children.json'), + ('common', 'treks.json'), + ('common', 'treks.json'), + ('trekking', 'trek_no_children.json')] + + # Mock GET mocked_get.return_value.status_code = 200 mocked_get.return_value.json = self.mock_json - self.assertEqual(Trek.objects.count(), 0) + mocked_get.return_value.content = b'' + mocked_head.return_value.status_code = 200 + call_command('import', 'geotrek.common.tests.test_parsers.GeotrekTrekTestProviderParser', verbosity=0) self.assertEqual(Trek.objects.count(), 1) t = Trek.objects.first() @@ -704,9 +715,26 @@ def test_delete_according_to_provider(self, mocked_get): self.assertEqual(set([t.pk, t2.pk, t3.pk]), set(Trek.objects.values_list('pk', flat=True))) @mock.patch('requests.get') - def test_delete_according_to_no_provider(self, mocked_get): + @mock.patch('requests.head') + def test_delete_according_to_no_provider(self, mocked_head, mocked_get): + self.mock_time = 0 + self.mock_json_order = [ + ('common', 'treks.json'), + ('common', 'treks.json'), + ('trekking', 'trek_no_children.json'), + ('common', 'treks.json'), + ('common', 'treks.json'), + ('trekking', 'trek_no_children.json'), + ('common', 'treks.json'), + ('common', 'treks.json'), + ('trekking', 'trek_no_children.json')] + + # Mock GET mocked_get.return_value.status_code = 200 mocked_get.return_value.json = self.mock_json + mocked_get.return_value.content = b'' + mocked_head.return_value.status_code = 200 + self.assertEqual(Trek.objects.count(), 0) call_command('import', 'geotrek.common.tests.test_parsers.GeotrekTrekTestNoProviderParser', verbosity=0) self.assertEqual(Trek.objects.count(), 1) @@ -838,6 +866,8 @@ def test_geotrek_aggregator_parser(self, mocked_head, mocked_get): ('trekking', 'trek_ids.json'), ('trekking', 'trek.json'), ('trekking', 'trek_children.json'), + ('trekking', 'trek_published_step.json'), + ('trekking', 'trek_unpublished_step.json'), ('trekking', 'poi_ids.json'), ('trekking', 'poi.json'), ('tourism', 'informationdesk_ids.json'), @@ -863,6 +893,8 @@ def test_geotrek_aggregator_parser(self, mocked_head, mocked_get): ('trekking', 'trek_ids.json'), ('trekking', 'trek.json'), ('trekking', 'trek_children.json'), + ('trekking', 'trek_published_step.json'), + ('trekking', 'trek_unpublished_step.json'), ('trekking', 'poi_ids.json'), ('trekking', 'poi.json'), ('tourism', 'informationdesk_ids.json'), @@ -885,9 +917,11 @@ def test_geotrek_aggregator_parser(self, mocked_head, mocked_get): string_parser = output.getvalue() self.assertIn('0000: Trek (URL_1) (00%)', string_parser) self.assertIn('0000: Poi (URL_1) (00%)', string_parser) - self.assertIn('5/5 lignes importées.', string_parser) + # Published Tour steps are imported twice, but created once + self.assertIn('7/7 lignes importées.', string_parser) + self.assertIn('6 enregistrements créés.', string_parser) self.assertIn('2/2 lignes importées.', string_parser) - self.assertEqual(Trek.objects.count(), 5) + self.assertEqual(Trek.objects.count(), 6) self.assertEqual(POI.objects.count(), 2) self.assertEqual(1, Trek.objects.get(name="Foo").information_desks.count()) self.assertEqual("Office de Tourisme de Seix", diff --git a/geotrek/trekking/parsers.py b/geotrek/trekking/parsers.py index 0d05770c9e..5a863e197e 100644 --- a/geotrek/trekking/parsers.py +++ b/geotrek/trekking/parsers.py @@ -197,18 +197,17 @@ def filter_points_reference(self, src, val): def end(self): """Add children after all treks imported are created in database.""" - super().end() self.next_url = f"{self.url}/api/v2/tour" try: params = { 'in_bbox': ','.join([str(coord) for coord in self.bbox.extent]), - 'fields': 'steps,uuid' + 'fields': 'steps,id' } response = self.request_or_retry(f"{self.next_url}", params=params) results = response.json()['results'] final_children = {} for result in results: - final_children[result['uuid']] = [step['uuid'] for step in result['steps']] + final_children[result['uuid']] = [step['id'] for step in result['steps']] for key, value in final_children.items(): if value: @@ -217,18 +216,18 @@ def end(self): self.add_warning(_(f"Trying to retrieve children for missing trek : could not find trek with UUID {key}")) return order = 0 - for child in value: - try: - trek_child_instance = Trek.objects.get(eid=child) - except Trek.DoesNotExist: - self.add_warning(_(f"One trek has not be generated for {trek_parent_instance[0].name} : could not find trek with UUID {child}")) - continue + for child_id in value: + response = self.request_or_retry(f"{self.url}/api/v2/trek/{child_id}") + child_trek = response.json() + self.parse_row(child_trek) + trek_child_instance = self.obj OrderedTrekChild.objects.update_or_create(parent=trek_parent_instance[0], child=trek_child_instance, defaults={'order': order}) order += 1 except Exception as e: self.add_warning(_(f"An error occured in children generation : {getattr(e, 'message', repr(e))}")) + super().end() class GeotrekServiceParser(GeotrekParser): diff --git a/geotrek/trekking/tests/data/geotrek_parser_v2/trek_children.json b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_children.json index 16226a3287..84502ccaf9 100644 --- a/geotrek/trekking/tests/data/geotrek_parser_v2/trek_children.json +++ b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_children.json @@ -7,7 +7,10 @@ "uuid": "9e70b294-1134-4c50-9c56-d722720cacf1", "steps": [ { - "uuid": "c9567576-2934-43ab-979e-e13d02c671a9" + "id": 10439 + }, + { + "id": 10442 } ] }, diff --git a/geotrek/trekking/tests/data/geotrek_parser_v2/trek_children_do_not_exist.json b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_children_do_not_exist.json index ed743a54b3..c66237ec49 100644 --- a/geotrek/trekking/tests/data/geotrek_parser_v2/trek_children_do_not_exist.json +++ b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_children_do_not_exist.json @@ -7,10 +7,10 @@ "uuid": "9e70b294-1134-4c50-9c56-d722720cacf1", "steps": [ { - "uuid": "c9567576-2934-43ab-979e-e13d02c671a9" + "id": 1234 }, { - "uuid": "c9567576-2934-43ab-666e-e13d02c671a9" + "id": 1235 } ] }, @@ -34,7 +34,7 @@ "uuid": "b2aea666-5e6e-4daa-a750-7d2ee52d3fe1", "steps": [ { - "uuid": "c9567576-2934-43ab-979e-e13d02c671a9" + "id": 457 } ] } diff --git a/geotrek/trekking/tests/data/geotrek_parser_v2/trek_no_children.json b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_no_children.json new file mode 100644 index 0000000000..93133b7ef5 --- /dev/null +++ b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_no_children.json @@ -0,0 +1,27 @@ +{ + "count": 5, + "next": null, + "previous": null, + "results": [ + { + "uuid": "9e70b294-1134-4c50-9c56-d722720cacf1", + "steps": [] + }, + { + "uuid": "1ba24605-aff2-4b16-bf30-6de1ebfb2a12", + "steps": [] + }, + { + "uuid": "6761143f-9244-41d0-b1af-21114408f769", + "steps": [] + }, + { + "uuid": "c9567576-2934-43ab-979e-e13d02c671a9", + "steps": [] + }, + { + "uuid": "b2aea892-5e6e-4daa-a750-7d2ee52d3fe1", + "steps": [] + } + ] +} diff --git a/geotrek/trekking/tests/data/geotrek_parser_v2/trek_not_found.json b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_not_found.json new file mode 100644 index 0000000000..0a48448444 --- /dev/null +++ b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_not_found.json @@ -0,0 +1,3 @@ +{ + "detail": "No Trek matches the given query." +} diff --git a/geotrek/trekking/tests/data/geotrek_parser_v2/trek_published_step.json b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_published_step.json new file mode 100644 index 0000000000..6c7dc87b14 --- /dev/null +++ b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_published_step.json @@ -0,0 +1,209 @@ +{ + "id": 10439, + "access": { + "fr": "Bonnac Irazein", + "en": "", + "it": "" + }, + "accessibilities": [], + "accessibility_advice": { + "fr": "", + "en": null, + "it": null + }, + "accessibility_covering": { + "fr": "", + "en": null, + "it": null + }, + "accessibility_exposure": { + "fr": "", + "en": null, + "it": null + }, + "accessibility_level": null, + "accessibility_signage": { + "fr": "", + "en": null, + "it": null + }, + "accessibility_slope": { + "fr": "", + "en": null, + "it": null + }, + "accessibility_width": { + "fr": "", + "en": null, + "it": null + }, + "advice": { + "fr": "", + "en": "", + "it": "" + }, + "advised_parking": { + "fr": "", + "en": "", + "it": "" + }, + "altimetric_profile": "https://foo.fr/api/v2/trek/10439/profile/", + "ambiance": { + "fr": "Je suis une bonne ambiance.", + "en": "", + "it": "" + }, + "arrival": { + "fr": "Ourjout", + "en": "", + "it": "" + }, + "ascent": 203, + "attachments": [ + { + "backend": "", + "type": "image", + "author": "Borvan53, CC-By-SA 4.0", + "license": null, + "thumbnail": "https://foo.fr/media/paperclip/trekking_trek/10439/bocard_deylie_2013_01.JPG.400x0_q85.jpg", + "legend": "Vue du site du bocard d'Eylie", + "title": "", + "url": "https://foo.fr/media/paperclip/trekking_trek/10439/bocard_deylie_2013_01.JPG", + "uuid": "2ed7ebc0-39ed-482c-bae3-0b1182f27d3d" + }, + { + "backend": "", + "type": "image", + "author": "", + "license": null, + "thumbnail": "https://foo.fr/media/paperclip/trekking_trek/10439/eeaio.jpeg.400x0_q85.jpg", + "legend": "", + "title": "éèàïô", + "url": "https://foo.fr/media/paperclip/trekking_trek/10439/eeaio.jpeg", + "uuid": "05c0c4ad-69bd-4b86-a8dc-3cbc74ecc4b6" + } + ], + "attachments_accessibility": [], + "children": [], + "cities": [ + "09290", + "09059", + "09317", + "09062" + ], + "create_datetime": "2019-07-23T09:09:53.090318Z", + "departure": { + "fr": "Eylé", + "en": "", + "es": "", + "it": "" + }, + "departure_city": "09290", + "departure_geom": [ + 0.9377712652787816, + 42.83789927043632 + ], + "descent": -564, + "description": { + "fr": "Dede est au bar.", + "en": "", + "it": "" + }, + "description_teaser": { + "fr": "Chapeau a fleur.", + "en": "", + "it": "" + }, + "difficulty": 2, + "disabled_infrastructure": { + "fr": "", + "en": null, + "it": null + }, + "duration": 6.0, + "elevation_area_url": "https://foo.fr/api/v2/trek/10439/dem/", + "elevation_svg_url": "https://foo.fr/api/v2/trek/10439/profile/?language=fr&format=svg", + "external_id": null, + "gear": { + "fr": "", + "en": null, + "it": null + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + 0.9377713, + 42.8378993, + 912.0 + ], + [ + 0.9377673, + 42.8379281, + 913.0 + ] + ] + }, + "gpx": "https://foo.fr/api/fr/treks/10439/deyle-a-ourjout.gpx", + "information_desks": [], + "kml": "https://foo.fr/api/fr/treks/10439/deyle-a-ourjout.kml", + "labels": [], + "length_2d": 12856.3, + "length_3d": 12904.9, + "max_elevation": 927, + "min_elevation": 551, + "name": { + "fr": "Foo", + "en": "Bar", + "it": "" + }, + "networks": [], + "next": { + "2": null, + "10445": 10441 + }, + "parents": [ + 2, + 10445 + ], + "parking_location": null, + "pdf": { + "fr": "https://foo.fr/api/fr/treks/10439/deyle-a-ourjout.pdf", + "en": "https://foo.fr/api/en/treks/10439/deyle-a-ourjout.pdf", + "it": "https://foo.fr/api/it/treks/10439/deyle-a-ourjout.pdf" + }, + "points_reference": null, + "portal": [], + "practice": 4, + "ratings": [], + "ratings_description": { + "fr": "", + "en": null, + "it": null + }, + "previous": { + "2": null, + "10445": null + }, + "public_transport": { + "fr": "", + "en": "", + "it": "" + }, + "published": { + "fr": true, + "en": false, + "it": false + }, + "reservation_system": null, + "reservation_id": "", + "route": 3, + "second_external_id": null, + "source": [], + "structure": 3, + "themes": [], + "update_datetime": "2021-05-17T13:54:07.091500Z", + "url": "https://foo.fr/api/v2/trek/10439/", + "uuid": "c9567576-2934-43ab-979e-e13d02c671a9", + "web_links": [] +} diff --git a/geotrek/trekking/tests/data/geotrek_parser_v2/trek_unpublished_step.json b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_unpublished_step.json new file mode 100644 index 0000000000..f07733f15d --- /dev/null +++ b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_unpublished_step.json @@ -0,0 +1,308 @@ + { + "id": 10442, + "access": { + "fr": "", + "en": "", + "it": "" + }, + "accessibilities": [ + 1 + ], + "accessibility_advice": { + "fr": "", + "en": "", + "it": "" + }, + "accessibility_covering": { + "fr": "", + "en": "", + "it": "" + }, + "accessibility_exposure": { + "fr": "", + "en": "", + "it": "" + }, + "accessibility_level": null, + "accessibility_signage": { + "fr": "", + "en": "", + "it": "" + }, + "accessibility_slope": { + "fr": "", + "en": "", + "it": "" + }, + "accessibility_width": { + "fr": "", + "en": "", + "it": "" + }, + "advice": { + "fr": "

Attention en cas d'orage. Fortement déconseillé par mauvais temps!

", + "en": "", + "it": "" + }, + "advised_parking": { + "fr": "Avant le Port de Lers", + "en": "", + "it": "" + }, + "altimetric_profile": "https://foo.fr/api/v2/trek/2/profile/", + "ambiance": { + "fr": "

Le nom de ce pic est issu de la légende selon laquelle les trois seigneurs des vallées de Massat, Vicdessos et Rabat-les-Trois-Seigneurs, se rencontraient sur la dalle plate en son sommet afin de débattre des droits des différentes vallées qu'ils administraient.

\r\n

\r\n

À partir du xviie siècle, de grandes caravanes d'ânes et de mulets transportaient le charbon de bois entre les forêts du Couserans et les forges à la catalane de la vallée de Rabat via le col de la Pourtanelle sur l'épaulement nord du pic.

\r\n

\r\n

Au xixe siècle, des porteurs de glace venaient y chercher leur butin sur le flanc nord du pic au glacier d'Ambans pour le transporter ensuite vers Toulouse. Ce glacier a totalement disparu au début du xxie siècle.

\r\n

\r\n

\r\n

Source Wikipedia

\r\n

", + "en": "Ambiance en", + "it": "" + }, + "arrival": { + "fr": "Sur la route", + "en": "", + "it": "" + }, + "ascent": 666, + "attachments": [ + { + "backend": "", + "type": "image", + "author": "Grégory Tonon", + "license": "License", + "thumbnail": "https://foo.fr/media/paperclip/trekking_trek/2/1024px-les_pyrenees_depuis_le_pic_des_3_seigneurs.jpg.400x0_q85.jpg", + "legend": "Vue sur la chaîne des Pyrénées, depuis le pics des 3 Seigneurs", + "title": "1024px-Les_Pyrénées_depuis_le_pic_des_3_Seigneurs", + "url": "https://foo.fr/media/paperclip/trekking_trek/2/1024px-les_pyrenees_depuis_le_pic_des_3_seigneurs.jpg", + "uuid": "8c62ae5f-9533-4de6-a863-3e33cd42d16c" + }, + { + "backend": "Attachment", + "type": "video", + "author": "Ariège Pyrénées", + "license": null, + "thumbnail": "", + "legend": "Grands site Occitanie - collection Ariège", + "title": "", + "url": "https://www.youtube.com/watch?v=O5fwnNceuks", + "uuid": "aeffbba4-821a-4f7b-af74-e47ed628679c" + }, + { + "backend": "", + "type": "file", + "author": "", + "license": null, + "thumbnail": "", + "legend": "", + "title": "file_example_MP3_700KB", + "url": "https://foo.fr/media/paperclip/trekking_trek/2/file_example_mp3_700kb.mp3", + "uuid": "529e754b-e5a8-4fe7-944d-161b4900a62e" + } + ], + "attachments_accessibility": [], + "children": [], + "cities": [ + "09231", + "09302" + ], + "create_datetime": "2013-12-12T16:20:01.405056Z", + "departure": { + "fr": "Port de Lers", + "en": "Lers bridge", + "it": "" + }, + "departure_city": "09231", + "departure_geom": [ + 1.411681003952174, + 42.80641572814877 + ], + "descent": -777, + "description": { + "fr": "https://foo.fr/media/paperclip/trekking_trek/2/file_example_mp3_700kb.mp3", + "en": "", + "it": "" + }, + "description_teaser": { + "fr": "

Un très joli point de vue, en retrait de la chaîne des Pyrénées.

", + "en": "", + "it": "" + }, + "difficulty": 1, + "disabled_infrastructure": { + "fr": "Accessibilité aménagement", + "en": "", + "it": "" + }, + "duration": 24.0, + "elevation_area_url": "https://foo.fr/api/v2/trek/2/dem/", + "elevation_svg_url": "https://foo.fr/api/v2/trek/2/profile/?language=fr&format=svg", + "external_id": null, + "gear": { + "fr": "Il faut de la corde", + "en": "", + "it": "" + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + 1.411681, + 42.8064157, + 1516.0 + ], + [ + 1.4117038, + 42.8065905, + 1516.0 + ] + ] + }, + "gpx": "https://foo.fr/api/fr/treks/2/boucle-du-pic-des-trois-seigneurs.gpx", + "information_desks": [ + 2, + 1, + 3 + ], + "kml": "https://foo.fr/api/fr/treks/2/boucle-du-pic-des-trois-seigneurs.kml", + "labels": [ + 1, + 2, + 3 + ], + "length_2d": 7606.3, + "length_3d": 7811.9, + "max_elevation": 2042, + "min_elevation": 1358, + "name": { + "fr": "Etape non publiée", + "en": "Unpublished step", + "it": "" + }, + "networks": [ + 2 + ], + "next": {}, + "parents": [], + "parking_location": [ + 1.412816, + 42.8063269 + ], + "pdf": { + "fr": "https://foo.fr/api/fr/treks/2/boucle-du-pic-des-trois-seigneurs.pdf", + "en": "https://foo.fr/api/en/treks/2/boucle-du-pic-des-trois-seigneurs.pdf", + "it": "https://foo.fr/api/it/treks/2/boucle-du-pic-des-trois-seigneurs.pdf" + }, + "points_reference": { + "type": "MultiPoint", + "coordinates": [ + [ + 1.411417008494028, + 42.81070319713575 + ], + [ + 1.415279389475474, + 42.81693648180148 + ], + [ + 1.403348923777236, + 42.825246550724195 + ], + [ + 1.428325654123916, + 42.8286458024494 + ], + [ + 1.437852860544806, + 42.81611800550653 + ], + [ + 1.423759460449225, + 42.807239989743145 + ] + ] + }, + "portal": [], + "practice": 3, + "ratings": [], + "ratings_description": { + "fr": "", + "en": "", + "it": "" + }, + "previous": {}, + "public_transport": { + "fr": "Test", + "en": "", + "it": "" + }, + "published": { + "fr": true, + "en": true, + "it": false + }, + "reservation_system": null, + "reservation_id": "", + "route": 1, + "second_external_id": null, + "source": [ + 2 + ], + "structure": 1, + "themes": [ + 8, + 4 + ], + "update_datetime": "2022-05-16T12:10:59.927409Z", + "url": "https://foo.fr/api/v2/trek/2/", + "uuid": "9e70b294-1134-4c50-9c56-d722720cace6", + "web_links": [ + { + "name": { + "fr": "Camping", + "en": "Camping", + "it": null + }, + "url": "http://camping.com/", + "category": { + "label": { + "fr": "A lire", + "en": null, + "it": null + }, + "id": 4, + "pictogram": "https://foo.fr/media/upload/weblink-book.png" + } + }, + { + "name": { + "fr": "Makina Corpus", + "en": "Makina Corpus", + "it": null + }, + "url": "http://makina-corpus.com/", + "category": { + "label": { + "fr": "A lire", + "en": null, + "it": null + }, + "id": 4, + "pictogram": "https://foo.fr/media/upload/weblink-book.png" + } + }, + { + "name": { + "fr": "Test", + "en": "", + "it": "" + }, + "url": "http://toto.com", + "category": { + "label": { + "fr": "A lire", + "en": null, + "it": null + }, + "id": 4, + "pictogram": "https://foo.fr/media/upload/weblink-book.png" + } + } + ] + } diff --git a/geotrek/trekking/tests/data/geotrek_parser_v2/trek_wrong_children.json b/geotrek/trekking/tests/data/geotrek_parser_v2/trek_wrong_children.json deleted file mode 100644 index a6ab1d4325..0000000000 --- a/geotrek/trekking/tests/data/geotrek_parser_v2/trek_wrong_children.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "count": 5, - "next": null, - "previous": null, - "results": [ - { - "uuid": "9e70b294-1134-4c50-9c56-d722720cacf1" - }, - { - "uuid": "1ba24605-aff2-4b16-bf30-6de1ebfb2a12" - }, - { - "uuid": "6761143f-9244-41d0-b1af-21114408f769" - }, - { - "uuid": "c9567576-2934-43ab-979e-e13d02c671a9" - }, - { - "uuid": "b2aea892-5e6e-4daa-a750-7d2ee52d3fe1" - } - ] -} diff --git a/geotrek/trekking/tests/test_parsers.py b/geotrek/trekking/tests/test_parsers.py index 290b175d17..2ccf04bc79 100644 --- a/geotrek/trekking/tests/test_parsers.py +++ b/geotrek/trekking/tests/test_parsers.py @@ -263,7 +263,9 @@ def test_create(self, mocked_head, mocked_get): ('trekking', 'sources.json'), ('trekking', 'trek_ids.json'), ('trekking', 'trek.json'), - ('trekking', 'trek_children.json')] + ('trekking', 'trek_children.json'), + ('trekking', 'trek_published_step.json'), + ('trekking', 'trek_unpublished_step.json')] # Mock GET mocked_get.return_value.status_code = 200 @@ -272,7 +274,7 @@ def test_create(self, mocked_head, mocked_get): mocked_head.return_value.status_code = 200 call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrekTrekParser', verbosity=0) - self.assertEqual(Trek.objects.count(), 5) + self.assertEqual(Trek.objects.count(), 6) trek = Trek.objects.all().first() self.assertEqual(trek.name, "Boucle du Pic des Trois Seigneurs") self.assertEqual(trek.name_it, "Foo bar") @@ -288,6 +290,7 @@ def test_create(self, mocked_head, mocked_get): self.assertAlmostEqual(trek.geom[0][0], 569946.9850365581, places=5) self.assertAlmostEqual(trek.geom[0][1], 6190964.893167565, places=5) self.assertEqual(trek.children.first().name, "Foo") + self.assertEqual(trek.children.last().name, "Etape non publiée") self.assertEqual(trek.labels.count(), 3) self.assertEqual(trek.source.first().name, "Une source numero 2") self.assertEqual(trek.source.first().website, "https://www.ecrins-parcnational.fr") @@ -312,7 +315,11 @@ class MockResponse: ('trekking', 'trek_ids.json'), ('trekking', 'trek.json'), ('trekking', 'trek_children.json'), - ('trekking', 'trek_children.json')] + ('trekking', 'trek_published_step.json'), + ('trekking', 'trek_unpublished_step.json'), + ('trekking', 'trek_children.json'), + ('trekking', 'trek_published_step.json'), + ('trekking', 'trek_unpublished_step.json')] mock_time = 0 total_mock_response = 1 @@ -341,7 +348,7 @@ def content(self): mocked_head.return_value.status_code = 200 call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrekTrekParser', verbosity=0) - self.assertEqual(Trek.objects.count(), 5) + self.assertEqual(Trek.objects.count(), 6) trek = Trek.objects.all().first() self.assertEqual(trek.name, "Boucle du Pic des Trois Seigneurs") self.assertEqual(trek.name_it, "Foo bar") @@ -372,7 +379,9 @@ def test_create_attachment_max_size(self, mocked_head, mocked_get): ('trekking', 'sources.json'), ('trekking', 'trek_ids.json'), ('trekking', 'trek.json'), - ('trekking', 'trek_children.json')] + ('trekking', 'trek_children.json'), + ('trekking', 'trek_published_step.json'), + ('trekking', 'trek_unpublished_step.json')] # Mock GET mocked_get.return_value.status_code = 200 @@ -381,7 +390,7 @@ def test_create_attachment_max_size(self, mocked_head, mocked_get): mocked_head.return_value.status_code = 200 call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrekTrekParser', verbosity=0) - self.assertEqual(Trek.objects.count(), 5) + self.assertEqual(Trek.objects.count(), 6) self.assertEqual(Attachment.objects.count(), 0) @mock.patch('requests.get') @@ -401,7 +410,9 @@ class MockResponse: ('trekking', 'sources.json'), ('trekking', 'trek_ids.json'), ('trekking', 'trek.json'), - ('trekking', 'trek_children.json')] + ('trekking', 'trek_children.json'), + ('trekking', 'trek_published_step.json'), + ('trekking', 'trek_unpublished_step.json')] mock_time = 0 a = 0 @@ -430,15 +441,15 @@ def content(self): mocked_head.return_value.status_code = 200 call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrekTrekParser', verbosity=0) - self.assertEqual(Trek.objects.count(), 5) + self.assertEqual(Trek.objects.count(), 6) trek = Trek.objects.all().first() self.assertEqual(Attachment.objects.filter(object_id=trek.pk).count(), 3) - self.assertEqual(Attachment.objects.first().attachment_file.read(), b'15') + self.assertEqual(Attachment.objects.first().attachment_file.read(), b'20') call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrekTrekParser', verbosity=0) - self.assertEqual(Trek.objects.count(), 5) + self.assertEqual(Trek.objects.count(), 6) trek.refresh_from_db() self.assertEqual(Attachment.objects.filter(object_id=trek.pk).count(), 3) - self.assertEqual(Attachment.objects.first().attachment_file.read(), b'25') + self.assertEqual(Attachment.objects.first().attachment_file.read(), b'35') @mock.patch('requests.get') @mock.patch('requests.head') @@ -458,6 +469,8 @@ def test_create_multiple_fr(self, mocked_head, mocked_get): ('trekking', 'trek_ids.json'), ('trekking', 'trek.json'), ('trekking', 'trek_children.json'), + ('trekking', 'trek_published_step.json'), + ('trekking', 'trek_unpublished_step.json'), ('trekking', 'structure.json'), ('trekking', 'trek_difficulty.json'), ('trekking', 'trek_route.json'), @@ -469,7 +482,7 @@ def test_create_multiple_fr(self, mocked_head, mocked_get): ('trekking', 'sources.json'), ('trekking', 'trek_ids_2.json'), ('trekking', 'trek_2.json'), - ('trekking', 'trek_children.json'), + ('trekking', 'trek_no_children.json'), ('trekking', 'structure.json'), ('trekking', 'trek_difficulty.json'), ('trekking', 'trek_route.json'), @@ -481,7 +494,7 @@ def test_create_multiple_fr(self, mocked_head, mocked_get): ('trekking', 'sources.json'), ('trekking', 'trek_ids_2.json'), ('trekking', 'trek_2_after.json'), - ('trekking', 'trek_children.json'), ] + ('trekking', 'trek_no_children.json')] # Mock GET mocked_get.return_value.status_code = 200 @@ -490,7 +503,7 @@ def test_create_multiple_fr(self, mocked_head, mocked_get): mocked_head.return_value.status_code = 200 call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrekTrekParser', verbosity=0) - self.assertEqual(Trek.objects.count(), 5) + self.assertEqual(Trek.objects.count(), 6) trek = Trek.objects.all().first() self.assertEqual(trek.name, "Boucle du Pic des Trois Seigneurs") self.assertEqual(trek.name_en, "Loop of the pic of 3 lords") @@ -503,7 +516,7 @@ def test_create_multiple_fr(self, mocked_head, mocked_get): self.assertEqual(trek.labels.count(), 3) self.assertEqual(trek.labels.first().name, "Chien autorisé") call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrek2TrekParser', verbosity=0) - self.assertEqual(Trek.objects.count(), 6) + self.assertEqual(Trek.objects.count(), 7) trek = Trek.objects.get(name_fr="Étangs du Picot") self.assertEqual(trek.description_teaser_fr, "Chapeau") self.assertEqual(trek.description_teaser_it, "Cappello") @@ -517,7 +530,7 @@ def test_create_multiple_fr(self, mocked_head, mocked_get): self.assertEqual(trek.published_es, False) call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrek2TrekParser', verbosity=0) trek.refresh_from_db() - self.assertEqual(Trek.objects.count(), 6) + self.assertEqual(Trek.objects.count(), 7) self.assertEqual(trek.description_teaser_fr, "Chapeau 2") self.assertEqual(trek.description_teaser_it, "Cappello 2") self.assertEqual(trek.description_teaser_es, "Sombrero 2") @@ -547,6 +560,8 @@ def test_create_multiple_en(self, mocked_head, mocked_get): ('trekking', 'trek_ids.json'), ('trekking', 'trek.json'), ('trekking', 'trek_children.json'), + ('trekking', 'trek_published_step.json'), + ('trekking', 'trek_unpublished_step.json'), ('trekking', 'structure.json'), ('trekking', 'trek_difficulty.json'), ('trekking', 'trek_route.json'), @@ -558,7 +573,7 @@ def test_create_multiple_en(self, mocked_head, mocked_get): ('trekking', 'sources.json'), ('trekking', 'trek_ids_2.json'), ('trekking', 'trek_2.json'), - ('trekking', 'trek_children.json'), + ('trekking', 'trek_no_children.json'), ('trekking', 'structure.json'), ('trekking', 'trek_difficulty.json'), ('trekking', 'trek_route.json'), @@ -570,7 +585,7 @@ def test_create_multiple_en(self, mocked_head, mocked_get): ('trekking', 'sources.json'), ('trekking', 'trek_ids_2.json'), ('trekking', 'trek_2_after.json'), - ('trekking', 'trek_children.json')] + ('trekking', 'trek_no_children.json')] # Mock GET mocked_get.return_value.status_code = 200 @@ -579,7 +594,7 @@ def test_create_multiple_en(self, mocked_head, mocked_get): mocked_head.return_value.status_code = 200 call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrekTrekParser', verbosity=0) - self.assertEqual(Trek.objects.count(), 5) + self.assertEqual(Trek.objects.count(), 6) trek = Trek.objects.get(name_fr="Boucle du Pic des Trois Seigneurs") self.assertEqual(trek.name, "Loop of the pic of 3 lords") self.assertEqual(trek.name_en, "Loop of the pic of 3 lords") @@ -593,7 +608,7 @@ def test_create_multiple_en(self, mocked_head, mocked_get): self.assertEqual(trek.labels.count(), 3) self.assertEqual(trek.labels.first().name, "Dogs are great") call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrek2TrekParser', verbosity=0) - self.assertEqual(Trek.objects.count(), 6) + self.assertEqual(Trek.objects.count(), 7) trek = Trek.objects.get(name_fr="Étangs du Picot") self.assertEqual(trek.description_teaser_fr, "Chapeau") self.assertEqual(trek.description_teaser_it, "Cappello") @@ -607,7 +622,7 @@ def test_create_multiple_en(self, mocked_head, mocked_get): self.assertEqual(trek.published_es, False) call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrek2TrekParser', verbosity=0) trek.refresh_from_db() - self.assertEqual(Trek.objects.count(), 6) + self.assertEqual(Trek.objects.count(), 7) self.assertEqual(trek.description_teaser_fr, "Chapeau 2") self.assertEqual(trek.description_teaser_it, "Cappello 2") self.assertEqual(trek.description_teaser_es, "Sombrero 2") @@ -635,7 +650,9 @@ def test_children_do_not_exist(self, mocked_head, mocked_get): ('trekking', 'sources.json'), ('trekking', 'trek_ids.json'), ('trekking', 'trek.json'), - ('trekking', 'trek_children_do_not_exist.json')] + ('trekking', 'trek_children_do_not_exist.json'), + ('trekking', 'trek_published_step.json'), + ('trekking', 'trek_unpublished_step.json')] # Mock GET mocked_get.return_value.status_code = 200 @@ -645,7 +662,6 @@ def test_children_do_not_exist(self, mocked_head, mocked_get): output = StringIO() call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrekTrekParser', verbosity=2, stdout=output) - self.assertIn("One trek has not be generated for Boucle du Pic des Trois Seigneurs : could not find trek with UUID c9567576-2934-43ab-666e-e13d02c671a9,\n", output.getvalue()) self.assertIn("Trying to retrieve children for missing trek : could not find trek with UUID b2aea666-5e6e-4daa-a750-7d2ee52d3fe1", output.getvalue()) @mock.patch('requests.get') @@ -664,7 +680,8 @@ def test_wrong_children_error(self, mocked_head, mocked_get): ('trekking', 'sources.json'), ('trekking', 'trek_ids.json'), ('trekking', 'trek.json'), - ('trekking', 'trek_wrong_children.json'), ] + ('trekking', 'trek_children.json'), + ('trekking', 'trek_not_found.json')] # Mock GET mocked_get.return_value.status_code = 200 @@ -675,7 +692,7 @@ def test_wrong_children_error(self, mocked_head, mocked_get): call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrekTrekParser', verbosity=2, stdout=output) - self.assertIn("An error occured in children generation : KeyError('steps'", output.getvalue()) + self.assertIn("An error occured in children generation : ValueImportError", output.getvalue()) @mock.patch('requests.get') @mock.patch('requests.head') @@ -695,6 +712,8 @@ def test_updated(self, mocked_head, mocked_get): ('trekking', 'trek_ids.json'), ('trekking', 'trek.json'), ('trekking', 'trek_children.json'), + ('trekking', 'trek_published_step.json'), + ('trekking', 'trek_unpublished_step.json'), ('trekking', 'structure.json'), ('trekking', 'trek_difficulty.json'), ('trekking', 'trek_route.json'), @@ -707,7 +726,9 @@ def test_updated(self, mocked_head, mocked_get): ('trekking', 'sources.json'), ('trekking', 'trek_ids_2.json'), ('trekking', 'trek_2.json'), - ('trekking', 'trek_children.json')] + ('trekking', 'trek_children.json'), + ('trekking', 'trek_published_step.json'), + ('trekking', 'trek_unpublished_step.json')] # Mock GET mocked_get.return_value.status_code = 200 @@ -716,7 +737,7 @@ def test_updated(self, mocked_head, mocked_get): mocked_head.return_value.status_code = 200 call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrekTrekParser', verbosity=0) - self.assertEqual(Trek.objects.count(), 5) + self.assertEqual(Trek.objects.count(), 6) trek = Trek.objects.all().first() self.assertEqual(trek.name, "Boucle du Pic des Trois Seigneurs") self.assertEqual(trek.name_fr, "Boucle du Pic des Trois Seigneurs") @@ -729,8 +750,8 @@ def test_updated(self, mocked_head, mocked_get): self.assertEqual(trek.labels.count(), 3) self.assertEqual(trek.labels.first().name, "Chien autorisé") call_command('import', 'geotrek.trekking.tests.test_parsers.TestGeotrekTrekParser', verbosity=0) - # Trek 2 is still in ids (trek_ids_2) => it's not removed - self.assertEqual(Trek.objects.count(), 2) + # Trek 2 is still in ids (trek_ids_2) => it's not removed, and neither are its children + self.assertEqual(Trek.objects.count(), 4) trek = Trek.objects.all().first() self.assertEqual(trek.name, "Boucle du Pic des Trois Seigneurs")