|
1 | 1 | import logging |
| 2 | +import operator |
2 | 3 | import typing |
3 | 4 | from contextlib import contextmanager |
4 | 5 | from datetime import datetime |
|
9 | 10 | from django.db.models.signals import pre_save |
10 | 11 | from ulid import ULID |
11 | 12 |
|
| 13 | +from apps.common.models import AssetTypeEnum |
12 | 14 | from apps.common.utils import decode_tasks, remove_object_keys |
13 | 15 | from apps.contributor.factories import ContributorUserFactory |
14 | 16 | from apps.contributor.models import ContributorUserGroup |
|
20 | 22 | MappingSessionUserGroup, |
21 | 23 | MappingSessionUserGroupTemp, |
22 | 24 | ) |
23 | | -from apps.project.models import Organization, Project |
| 25 | +from apps.project.models import ( |
| 26 | + Organization, |
| 27 | + Project, |
| 28 | + ProjectAsset, |
| 29 | + ProjectAssetExportTypeEnum, |
| 30 | + ProjectAssetInputTypeEnum, |
| 31 | +) |
| 32 | +from apps.project.tests.e2e_create_project_tile_map_service_test import read_csv, read_json |
24 | 33 | from apps.tutorial.models import Tutorial |
25 | 34 | from apps.user.factories import UserFactory |
26 | 35 | from main.config import Config |
@@ -618,3 +627,225 @@ def _test_project(self, filename: str): |
618 | 627 |
|
619 | 628 | project.refresh_from_db() |
620 | 629 | assert project.progress == test_data["expected_pulled_results_data"]["progress"] |
| 630 | + |
| 631 | + # Check if progress and contributorCount synced to firebase |
| 632 | + project_fb_data = project_fb_ref.get() |
| 633 | + assert project_fb_data is not None, "Project in firebase is None" |
| 634 | + assert isinstance(project_fb_data, dict), "Project in firebase should be a dictionary" |
| 635 | + assert project_fb_data["progress"] == project.progress, "Progress should be synced with firebase" |
| 636 | + assert project_fb_data["contributorCount"] == 1, "Contributor count should be synced with firebase" |
| 637 | + |
| 638 | + # Check groups export |
| 639 | + groups_project_asset = ProjectAsset.objects.filter( |
| 640 | + project=project, |
| 641 | + type=AssetTypeEnum.EXPORT, |
| 642 | + export_type=ProjectAssetExportTypeEnum.GROUPS, |
| 643 | + ).first() |
| 644 | + assert groups_project_asset is not None, "Groups project asset not found" |
| 645 | + |
| 646 | + expected_groups = read_csv( |
| 647 | + Path(Config.BASE_DIR, test_data["expected_project_exports_data"]["groups"]), |
| 648 | + ignore_columns={ |
| 649 | + "total_area", # NOTE: previously empty, now real value |
| 650 | + "time_spent_max_allowed", # NOTE: previously empty, now real value |
| 651 | + }, |
| 652 | + ) |
| 653 | + actual_groups = read_csv( |
| 654 | + groups_project_asset.file, |
| 655 | + compressed=True, |
| 656 | + ignore_columns={ |
| 657 | + "total_area", # NOTE: previously empty, now real value |
| 658 | + "time_spent_max_allowed", # NOTE: previously empty, now real value |
| 659 | + "project_internal_id", # NOTE: added for referencing |
| 660 | + "group_internal_id", # NOTE: added for referencing |
| 661 | + }, |
| 662 | + ) |
| 663 | + assert expected_groups == actual_groups, "Difference found for groups export file." |
| 664 | + |
| 665 | + # Check tasks export |
| 666 | + tasks_project_asset = ProjectAsset.objects.filter( |
| 667 | + project=project, |
| 668 | + type=AssetTypeEnum.EXPORT, |
| 669 | + export_type=ProjectAssetExportTypeEnum.TASKS, |
| 670 | + ).first() |
| 671 | + assert tasks_project_asset is not None, "Tasks project asset not found" |
| 672 | + |
| 673 | + expected_tasks = read_csv( |
| 674 | + Path(Config.BASE_DIR, test_data["expected_project_exports_data"]["tasks"]), |
| 675 | + ignore_columns={ |
| 676 | + "", # NOTE: dataframe index |
| 677 | + "urlB", # FIXME: old system contains this field |
| 678 | + "tile_x", # FIXME: old system contains this field |
| 679 | + "tile_y", # FIXME: old system contains this field |
| 680 | + }, |
| 681 | + ) |
| 682 | + actual_tasks = read_csv( |
| 683 | + tasks_project_asset.file, |
| 684 | + compressed=True, |
| 685 | + ignore_columns={ |
| 686 | + "", # NOTE: dataframe index |
| 687 | + "project_internal_id", # NOTE: added for referencing |
| 688 | + "group_internal_id", # NOTE: added for referencing |
| 689 | + "task_internal_id", # NOTE: added for referencing |
| 690 | + }, |
| 691 | + ) |
| 692 | + assert expected_tasks == actual_tasks, "Difference found for tasks export file." |
| 693 | + |
| 694 | + # Check results export |
| 695 | + results_project_asset = ProjectAsset.objects.filter( |
| 696 | + project=project, |
| 697 | + type=AssetTypeEnum.EXPORT, |
| 698 | + export_type=ProjectAssetExportTypeEnum.RESULTS, |
| 699 | + ).first() |
| 700 | + assert results_project_asset is not None, "Results project asset not found" |
| 701 | + |
| 702 | + expected_results = read_csv( |
| 703 | + Path(Config.BASE_DIR, test_data["expected_project_exports_data"]["results"]), |
| 704 | + sort_column=operator.itemgetter("task_id"), |
| 705 | + ignore_columns={ |
| 706 | + "", # NOTE: dataframe index |
| 707 | + }, |
| 708 | + ) |
| 709 | + actual_results = read_csv( |
| 710 | + results_project_asset.file, |
| 711 | + sort_column=operator.itemgetter("task_id"), |
| 712 | + ignore_columns={ |
| 713 | + "", # NOTE: dataframe index |
| 714 | + "task_internal_id", # NOTE: added for referencing |
| 715 | + "user_internal_id", # NOTE: added for referencing |
| 716 | + "group_internal_id", # NOTE: added for referencing |
| 717 | + "project_internal_id", # NOTE: added for referencing |
| 718 | + }, |
| 719 | + compressed=True, |
| 720 | + ) |
| 721 | + assert expected_results == actual_results, "Difference found for results export file." |
| 722 | + |
| 723 | + # Check aoi export |
| 724 | + aoi_project_asset = ProjectAsset.objects.filter( |
| 725 | + project=project, |
| 726 | + type=AssetTypeEnum.INPUT, |
| 727 | + input_type=ProjectAssetInputTypeEnum.AOI_GEOMETRY, |
| 728 | + ).first() |
| 729 | + assert aoi_project_asset is not None, "AOI Geometry project asset not found" |
| 730 | + |
| 731 | + expected_aoi = read_json( |
| 732 | + Path(Config.BASE_DIR, test_data["expected_project_exports_data"]["area_of_interest"]), |
| 733 | + ignore_fields={ |
| 734 | + "crs", # NOTE: crs has almost no data |
| 735 | + "name", # NOTE: previously system file path |
| 736 | + "properties", # FIXME: previously has id (index) |
| 737 | + "coordinates", # FIXME: precision has changed |
| 738 | + }, |
| 739 | + ) |
| 740 | + actual_aoi = read_json( |
| 741 | + aoi_project_asset.file, |
| 742 | + ignore_fields={ |
| 743 | + "properties", # FIXME: previously has id (index) |
| 744 | + "coordinates", # FIXME: precision has changed |
| 745 | + }, |
| 746 | + ) |
| 747 | + assert expected_aoi == actual_aoi, "Difference found for AOI geometry export file." |
| 748 | + |
| 749 | + # Check aggregated results export |
| 750 | + aggregated_results_project_asset = ProjectAsset.objects.filter( |
| 751 | + project=project, |
| 752 | + type=AssetTypeEnum.EXPORT, |
| 753 | + export_type=ProjectAssetExportTypeEnum.AGGREGATED_RESULTS, |
| 754 | + ).first() |
| 755 | + assert aggregated_results_project_asset is not None, "Aggregated results project asset not found" |
| 756 | + |
| 757 | + expected_aggregated_results = read_csv( |
| 758 | + Path(Config.BASE_DIR, test_data["expected_project_exports_data"]["aggregated_results"]), |
| 759 | + ignore_columns={ |
| 760 | + "urlB", # FIXME: old system contains this field |
| 761 | + "tile_x", # FIXME: old system contains this field |
| 762 | + "tile_y", # FIXME: old system contains this field |
| 763 | + "3_count", # FIXME: old system contains this field |
| 764 | + "3_share", # FIXME: old system contains this field |
| 765 | + }, |
| 766 | + ) |
| 767 | + actual_aggregated_results = read_csv( |
| 768 | + aggregated_results_project_asset.file, |
| 769 | + compressed=True, |
| 770 | + ignore_columns={ |
| 771 | + "project_internal_id", # NOTE: added for referencing |
| 772 | + "group_internal_id", # NOTE: added for referencing |
| 773 | + "task_internal_id", # NOTE: added for referencing |
| 774 | + "task_id.1", # FIXME: This column is extra |
| 775 | + "group_id.1", # FIXME: This column is extra |
| 776 | + }, |
| 777 | + ) |
| 778 | + |
| 779 | + assert expected_aggregated_results == actual_aggregated_results, ( |
| 780 | + "Difference found for aggregated results export file." |
| 781 | + ) |
| 782 | + |
| 783 | + # Check aggregated results with geometry export |
| 784 | + aggregated_results_with_geometry_project_asset = ProjectAsset.objects.filter( |
| 785 | + project=project, |
| 786 | + type=AssetTypeEnum.EXPORT, |
| 787 | + export_type=ProjectAssetExportTypeEnum.AGGREGATED_RESULTS_WITH_GEOMETRY, |
| 788 | + ).first() |
| 789 | + assert aggregated_results_with_geometry_project_asset is not None, ( |
| 790 | + "Aggregated results with geometry project asset not found" |
| 791 | + ) |
| 792 | + |
| 793 | + expected_aggregated_results_with_geometry = read_json( |
| 794 | + Path(Config.BASE_DIR, test_data["expected_project_exports_data"]["aggregated_results_with_geometry"]), |
| 795 | + ignore_fields={ |
| 796 | + "name", # NOTE: Previously "tmp", now "tmp" + random_str |
| 797 | + "urlB", # FIXME: old system contains this field |
| 798 | + "tile_x", # FIXME: old system contains this field |
| 799 | + "tile_y", # FIXME: old system contains this field |
| 800 | + "3_count", # FIXME: old system contains this field |
| 801 | + "3_share", # FIXME: old system contains this field |
| 802 | + }, |
| 803 | + ) |
| 804 | + actual_aggregated_results_with_geometry = read_json( |
| 805 | + aggregated_results_with_geometry_project_asset.file, |
| 806 | + compressed=True, |
| 807 | + ignore_fields={ |
| 808 | + "name", # NOTE: Previously "tmp", now "tmp" + random_str |
| 809 | + "project_internal_id", # NOTE: added for referencing |
| 810 | + "group_internal_id", # NOTE: added for referencing |
| 811 | + "task_internal_id", # NOTE: added for referencing |
| 812 | + "task_id.1", # FIXME: This column is extra |
| 813 | + "group_id.1", # FIXME: This column is extra |
| 814 | + }, |
| 815 | + ) |
| 816 | + assert expected_aggregated_results_with_geometry == actual_aggregated_results_with_geometry, ( |
| 817 | + "Difference found for aggregated results with geometry export file." |
| 818 | + ) |
| 819 | + |
| 820 | + # Check history export |
| 821 | + history_project_asset = ProjectAsset.objects.filter( |
| 822 | + project=project, |
| 823 | + type=AssetTypeEnum.EXPORT, |
| 824 | + export_type=ProjectAssetExportTypeEnum.HISTORY, |
| 825 | + ).first() |
| 826 | + assert history_project_asset is not None, "History project asset not found" |
| 827 | + |
| 828 | + expected_history = read_csv( |
| 829 | + Path(Config.BASE_DIR, test_data["expected_project_exports_data"]["history"]), |
| 830 | + ) |
| 831 | + actual_history = read_csv( |
| 832 | + history_project_asset.file, |
| 833 | + ) |
| 834 | + assert expected_history == actual_history, "Difference found for history export file." |
| 835 | + |
| 836 | + # Check users export |
| 837 | + users_project_asset = ProjectAsset.objects.filter( |
| 838 | + project=project, |
| 839 | + type=AssetTypeEnum.EXPORT, |
| 840 | + export_type=ProjectAssetExportTypeEnum.USERS, |
| 841 | + ).first() |
| 842 | + assert users_project_asset is not None, "Users project asset not found" |
| 843 | + |
| 844 | + expected_users = read_csv( |
| 845 | + Path(Config.BASE_DIR, test_data["expected_project_exports_data"]["users"]), |
| 846 | + ) |
| 847 | + actual_users = read_csv( |
| 848 | + users_project_asset.file, |
| 849 | + compressed=True, |
| 850 | + ) |
| 851 | + assert expected_users == actual_users, "Difference found for users export file." |
0 commit comments