|
39 | 39 | )
|
40 | 40 | from ..merginproject import pygeodiff
|
41 | 41 | from ..report import create_report
|
| 42 | +from ..editor import EditorHandler |
42 | 43 |
|
43 | 44 |
|
44 | 45 | SERVER_URL = os.environ.get("TEST_MERGIN_URL")
|
@@ -113,7 +114,12 @@ def server_has_editor_support(mc, access):
|
113 | 114 | Returns:
|
114 | 115 | bool: True if the server has editor support, False otherwise.
|
115 | 116 | """
|
116 |
| - return "editorsnames" in access and is_version_acceptable(mc.server_version(), "2024.4") |
| 117 | + return "editorsnames" in access and mc.has_editor_support() |
| 118 | + |
| 119 | + |
| 120 | +def test_client_instance(mc, mc2): |
| 121 | + assert isinstance(mc, MerginClient) |
| 122 | + assert isinstance(mc2, MerginClient) |
117 | 123 |
|
118 | 124 |
|
119 | 125 | def test_login(mc):
|
@@ -1191,42 +1197,36 @@ def test_download_diffs(mc):
|
1191 | 1197 |
|
1192 | 1198 | def test_modify_project_permissions(mc):
|
1193 | 1199 | test_project = "test_project"
|
1194 |
| - project = API_USER + "/" + test_project |
| 1200 | + test_project_fullname = API_USER + "/" + test_project |
1195 | 1201 | project_dir = os.path.join(TMP_DIR, test_project)
|
1196 | 1202 | download_dir = os.path.join(TMP_DIR, "download", test_project)
|
1197 | 1203 |
|
1198 |
| - cleanup(mc, project, [project_dir, download_dir]) |
| 1204 | + cleanup(mc, test_project_fullname, [project_dir, download_dir]) |
1199 | 1205 | # prepare local project
|
1200 | 1206 | shutil.copytree(TEST_DATA_DIR, project_dir)
|
1201 | 1207 |
|
1202 | 1208 | # create remote project
|
1203 |
| - mc.create_project_and_push(project, directory=project_dir) |
1204 |
| - |
1205 |
| - # check basic metadata about created project |
1206 |
| - project_info = mc.project_info(project) |
1207 |
| - assert project_info["version"] == "v1" |
1208 |
| - assert project_info["name"] == test_project |
1209 |
| - assert project_info["namespace"] == API_USER |
| 1209 | + mc.create_project_and_push(test_project_fullname, directory=project_dir) |
1210 | 1210 |
|
1211 |
| - permissions = mc.project_user_permissions(project) |
| 1211 | + permissions = mc.project_user_permissions(test_project_fullname) |
1212 | 1212 | assert permissions["owners"] == [API_USER]
|
1213 | 1213 | assert permissions["writers"] == [API_USER]
|
1214 | 1214 | assert permissions["readers"] == [API_USER]
|
1215 | 1215 | editor_support = server_has_editor_support(mc, permissions)
|
1216 | 1216 | if editor_support:
|
1217 | 1217 | assert permissions["editors"] == [API_USER]
|
1218 | 1218 |
|
1219 |
| - mc.add_user_permissions_to_project(project, [API_USER2], "writer") |
1220 |
| - permissions = mc.project_user_permissions(project) |
| 1219 | + mc.add_user_permissions_to_project(test_project_fullname, [API_USER2], "writer") |
| 1220 | + permissions = mc.project_user_permissions(test_project_fullname) |
1221 | 1221 | assert set(permissions["owners"]) == {API_USER}
|
1222 | 1222 | assert set(permissions["writers"]) == {API_USER, API_USER2}
|
1223 | 1223 | assert set(permissions["readers"]) == {API_USER, API_USER2}
|
1224 | 1224 | editor_support = server_has_editor_support(mc, permissions)
|
1225 | 1225 | if editor_support:
|
1226 | 1226 | assert set(permissions["editors"]) == {API_USER, API_USER2}
|
1227 | 1227 |
|
1228 |
| - mc.remove_user_permissions_from_project(project, [API_USER2]) |
1229 |
| - permissions = mc.project_user_permissions(project) |
| 1228 | + mc.remove_user_permissions_from_project(test_project_fullname, [API_USER2]) |
| 1229 | + permissions = mc.project_user_permissions(test_project_fullname) |
1230 | 1230 | assert permissions["owners"] == [API_USER]
|
1231 | 1231 | assert permissions["writers"] == [API_USER]
|
1232 | 1232 | assert permissions["readers"] == [API_USER]
|
@@ -2524,3 +2524,117 @@ def test_download_failure(mc):
|
2524 | 2524 | with open(job.failure_log_file, "r", encoding="utf-8") as f:
|
2525 | 2525 | content = f.read()
|
2526 | 2526 | assert "Traceback" in content
|
| 2527 | + |
| 2528 | + |
| 2529 | +# TODO: consider to use separate test_editor.py file for tests that require editor |
| 2530 | +def test_editor_handler(mc: MerginClient): |
| 2531 | + """Test editor handler class and push with editor""" |
| 2532 | + |
| 2533 | + project_info = {"role": "editor"} |
| 2534 | + # intilize handler |
| 2535 | + editor_handler = EditorHandler(mc, project_info) |
| 2536 | + if not mc.has_editor_support(): |
| 2537 | + assert editor_handler.is_enabled() is False |
| 2538 | + return |
| 2539 | + |
| 2540 | + # mock that user is editor |
| 2541 | + project_info["role"] = editor_handler.ROLE_NAME |
| 2542 | + assert editor_handler.is_enabled() is True |
| 2543 | + |
| 2544 | + # unit test for EditorHandler methods |
| 2545 | + qgs_changeset = { |
| 2546 | + "added": [{"path": "/folder/project.new.Qgz"}], |
| 2547 | + "updated": [{"path": "/folder/project.updated.Qgs"}], |
| 2548 | + "removed": [{"path": "/folder/project.removed.qgs"}], |
| 2549 | + } |
| 2550 | + qgs_changeset = editor_handler.filter_changes(qgs_changeset) |
| 2551 | + assert sum(len(v) for v in qgs_changeset.values()) == 0 |
| 2552 | + |
| 2553 | + mergin_config_changeset = { |
| 2554 | + "added": [{"path": "/.mergin/mergin-config.json"}], |
| 2555 | + "updated": [{"path": "/.mergin/mergin-config.json"}], |
| 2556 | + "removed": [{"path": "/.mergin/mergin-config.json"}], |
| 2557 | + } |
| 2558 | + mergin_config_changeset = editor_handler.filter_changes(mergin_config_changeset) |
| 2559 | + assert sum(len(v) for v in mergin_config_changeset.values()) == 0 |
| 2560 | + |
| 2561 | + gpkg_changeset = { |
| 2562 | + "added": [{"path": "/.mergin/data.gpkg"}], |
| 2563 | + "updated": [{"path": "/.mergin/conflict-data.gpkg"}, {"path": "/.mergin/data.gpkg", "diff": {}}], |
| 2564 | + "removed": [{"path": "/.mergin/data.gpkg"}], |
| 2565 | + } |
| 2566 | + gpkg_changeset = editor_handler.filter_changes(gpkg_changeset) |
| 2567 | + assert sum(len(v) for v in gpkg_changeset.values()) == 2 |
| 2568 | + assert gpkg_changeset["added"][0]["path"] == "/.mergin/data.gpkg" |
| 2569 | + assert gpkg_changeset["updated"][0]["path"] == "/.mergin/data.gpkg" |
| 2570 | + |
| 2571 | + |
| 2572 | +def test_editor_push(mc: MerginClient, mc2: MerginClient): |
| 2573 | + """Test push with editor""" |
| 2574 | + if not mc.has_editor_support(): |
| 2575 | + return |
| 2576 | + test_project = "test_editor_push" |
| 2577 | + test_project_fullname = API_USER + "/" + test_project |
| 2578 | + project = API_USER + "/" + test_project |
| 2579 | + project_dir = os.path.join(TMP_DIR, test_project) |
| 2580 | + cleanup(mc, project, [project_dir]) |
| 2581 | + |
| 2582 | + # create new (empty) project on server |
| 2583 | + # TODO: return project_info from create project, don't use project_full name for project info, instead returned id of project |
| 2584 | + mc.create_project(test_project) |
| 2585 | + |
| 2586 | + mc.add_user_permissions_to_project(project, [API_USER2], "editor") |
| 2587 | + project_info = mc2.project_info(test_project_fullname) |
| 2588 | + editor_handler = EditorHandler(mc2, project_info) |
| 2589 | + assert project_info["role"] == editor_handler.ROLE_NAME |
| 2590 | + assert editor_handler.is_enabled() is True |
| 2591 | + |
| 2592 | + # download empty project |
| 2593 | + mc2.download_project(test_project_fullname, project_dir) |
| 2594 | + |
| 2595 | + # editor is starting to adding qgis files and "normal" file |
| 2596 | + qgs_file_name = "test.qgs" |
| 2597 | + txt_file_name = "test.txt" |
| 2598 | + gpkg_file_name = "base.gpkg" |
| 2599 | + files_to_push = [qgs_file_name, txt_file_name, gpkg_file_name] |
| 2600 | + for file in files_to_push: |
| 2601 | + shutil.copy(os.path.join(TEST_DATA_DIR, file), project_dir) |
| 2602 | + # it's possible to push allowed files if editor |
| 2603 | + mc2.push_project(project_dir) |
| 2604 | + project_info = mc2.project_info(test_project_fullname) |
| 2605 | + assert len(project_info.get("files")) == len(files_to_push) - 1 # ggs is not pushed |
| 2606 | + # find pushed files in server |
| 2607 | + assert any(file["path"] == qgs_file_name for file in project_info.get("files")) is False |
| 2608 | + assert any(file["path"] == txt_file_name for file in project_info.get("files")) is True |
| 2609 | + assert any(file["path"] == gpkg_file_name for file in project_info.get("files")) is True |
| 2610 | + pull_changes, push_changes, push_changes_summary = mc.project_status(project_dir) |
| 2611 | + assert not sum(len(v) for v in pull_changes.values()) |
| 2612 | + assert sum(len(v) for v in push_changes.values()) == 1 |
| 2613 | + # ggs is still waiting to push |
| 2614 | + assert any(file["path"] == qgs_file_name for file in push_changes.get("added")) is True |
| 2615 | + |
| 2616 | + # editor is trying to psuh row to gpkg file -> it's possible |
| 2617 | + shutil.copy( |
| 2618 | + os.path.join(TEST_DATA_DIR, "inserted_1_A.gpkg"), |
| 2619 | + os.path.join(project_dir, gpkg_file_name), |
| 2620 | + ) |
| 2621 | + mc2.push_project(project_dir) |
| 2622 | + project_info = mc2.project_info(test_project_fullname) |
| 2623 | + pull_changes, push_changes, push_changes_summary = mc.project_status(project_dir) |
| 2624 | + assert any(file["path"] == gpkg_file_name for file in project_info.get("files")) is True |
| 2625 | + assert any(file["path"] == gpkg_file_name for file in push_changes.get("updated")) is False |
| 2626 | + |
| 2627 | + # editor is trying to insert tables to gpkg file |
| 2628 | + shutil.copy( |
| 2629 | + os.path.join(TEST_DATA_DIR, "two_tables.gpkg"), |
| 2630 | + os.path.join(project_dir, gpkg_file_name), |
| 2631 | + ) |
| 2632 | + mc2.push_project(project_dir) |
| 2633 | + pull_changes, push_changes, push_changes_summary = mc.project_status(project_dir) |
| 2634 | + assert not sum(len(v) for v in pull_changes.values()) |
| 2635 | + # gpkg was filter by editor_handler in push_project, because new tables added |
| 2636 | + assert sum(len(v) for v in push_changes.values()) == 2 |
| 2637 | + # ggs and gpkg are still waiting to push |
| 2638 | + assert any(file["path"] == qgs_file_name for file in push_changes.get("added")) is True |
| 2639 | + assert any(file["path"] == gpkg_file_name for file in push_changes.get("updated")) is True |
| 2640 | + |
0 commit comments