Skip to content

Commit 6e9f177

Browse files
committed
add tests
1 parent c118ca9 commit 6e9f177

File tree

4 files changed

+131
-40
lines changed

4 files changed

+131
-40
lines changed

server/mergin/sync/public_api_v2_controller.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
from mergin.sync.forms import project_name_validation
1111
from .files import ProjectFileSchema
1212

13-
from .schemas import ProjectMemberSchema, ProjectSchemaV2
13+
from .schemas import ProjectMemberSchema
14+
from .schemas_v2 import ProjectSchema
1415
from .workspace import WorkspaceRole
1516
from ..app import db
1617
from ..auth import auth_required
@@ -134,7 +135,7 @@ def remove_project_collaborator(id, user_id):
134135
def get_project(id, files_at_version=None):
135136
"""Get project info. Include list of files at specific version if requested."""
136137
project = require_project_by_uuid(id, ProjectPermissions.Read)
137-
data = ProjectSchemaV2().dump(project)
138+
data = ProjectSchema().dump(project)
138139
if files_at_version:
139140
pv = ProjectVersion.query.filter_by(
140141
project_id=project.id, name=ProjectVersion.from_v_name(files_at_version)

server/mergin/sync/schemas.py

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -405,40 +405,3 @@ class ProjectMemberSchema(Schema):
405405
project_role = fields.Enum(enum=ProjectRole, by_value=True)
406406
workspace_role = fields.Enum(enum=WorkspaceRole, by_value=True)
407407
role = fields.Enum(enum=ProjectRole, by_value=True)
408-
409-
410-
class ProjectSchemaV2(ma.SQLAlchemyAutoSchema):
411-
id = fields.UUID()
412-
name = fields.String()
413-
version = fields.Function(lambda obj: ProjectVersion.to_v_name(obj.latest_version))
414-
public = fields.Boolean()
415-
size = fields.Integer(attribute="disk_usage")
416-
417-
created_at = DateTimeWithZ(attribute="created")
418-
updated_at = DateTimeWithZ(attribute="updated")
419-
420-
workspace = fields.Function(
421-
lambda obj: {"id": obj.workspace.id, "name": obj.workspace.name}
422-
)
423-
role = fields.Method("_role")
424-
425-
def _role(self, obj):
426-
role = ProjectPermissions.get_user_project_role(obj, current_user)
427-
if not role:
428-
return None
429-
return role.value
430-
431-
class Meta:
432-
model = Project
433-
load_instance = True
434-
fields = (
435-
"id",
436-
"name",
437-
"version",
438-
"public",
439-
"size",
440-
"created_at",
441-
"updated_at",
442-
"workspace",
443-
"role",
444-
)

server/mergin/sync/schemas_v2.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Copyright (C) Lutra Consulting Limited
2+
#
3+
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-MerginMaps-Commercial
4+
5+
from marshmallow import fields
6+
from flask_login import current_user
7+
8+
from ..app import DateTimeWithZ, ma
9+
from .permissions import ProjectPermissions
10+
from .models import (
11+
Project,
12+
ProjectVersion,
13+
)
14+
15+
16+
class ProjectSchema(ma.SQLAlchemyAutoSchema):
17+
id = fields.UUID()
18+
name = fields.String()
19+
version = fields.Function(lambda obj: ProjectVersion.to_v_name(obj.latest_version))
20+
public = fields.Boolean()
21+
size = fields.Integer(attribute="disk_usage")
22+
23+
created_at = DateTimeWithZ(attribute="created")
24+
updated_at = DateTimeWithZ(attribute="updated")
25+
26+
workspace = fields.Function(
27+
lambda obj: {"id": obj.workspace.id, "name": obj.workspace.name}
28+
)
29+
role = fields.Method("_role")
30+
31+
def _role(self, obj):
32+
role = ProjectPermissions.get_user_project_role(obj, current_user)
33+
if not role:
34+
return None
35+
return role.value
36+
37+
class Meta:
38+
model = Project
39+
load_instance = True
40+
fields = (
41+
"id",
42+
"name",
43+
"version",
44+
"public",
45+
"size",
46+
"created_at",
47+
"updated_at",
48+
"workspace",
49+
"role",
50+
)

server/mergin/tests/test_public_api_v2.py

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
# Copyright (C) Lutra Consulting Limited
22
#
33
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-MerginMaps-Commercial
4-
from .utils import add_user
4+
from datetime import datetime
5+
6+
from . import DEFAULT_USER
7+
from .utils import (
8+
add_user,
9+
login,
10+
login_as_admin,
11+
create_workspace,
12+
create_project,
13+
upload_file_to_project,
14+
)
515
from ..app import db
616
from mergin.sync.models import Project
717
from tests import test_project, test_workspace_id
818

19+
from ..auth.models import User
920
from ..config import Configuration
1021
from ..sync.models import ProjectRole
1122

@@ -126,3 +137,69 @@ def test_project_members(client):
126137
# access provided by workspace role cannot be removed directly
127138
response = client.delete(url + f"/{user.id}")
128139
assert response.status_code == 404
140+
141+
142+
def test_get_project(client):
143+
"""Test get project info endpoint"""
144+
admin = User.query.filter_by(username=DEFAULT_USER[0]).first()
145+
test_workspace = create_workspace()
146+
project = create_project("new_project", test_workspace, admin)
147+
add_user("test_user", "ilovemergin")
148+
login(client, "test_user", "ilovemergin")
149+
# lack of permissions
150+
response = client.get(f"v2/projects/{project.id}")
151+
assert response.status_code == 403
152+
# access public project
153+
project.public = True
154+
db.session.commit()
155+
response = client.get(f"v2/projects/{project.id}")
156+
assert response.status_code == 200
157+
assert response.json["public"] is True
158+
# project scheduled for deletion
159+
login_as_admin(client)
160+
project.public = False
161+
project.removed_at = datetime.utcnow()
162+
db.session.commit()
163+
response = client.get(f"v2/projects/{project.id}")
164+
assert response.status_code == 404
165+
# success
166+
project.removed_at = None
167+
db.session.commit()
168+
response = client.get(f"v2/projects/{project.id}")
169+
assert response.status_code == 200
170+
expected_keys = {
171+
"id",
172+
"name",
173+
"workspace",
174+
"role",
175+
"version",
176+
"created_at",
177+
"updated_at",
178+
"public",
179+
"size",
180+
}
181+
assert expected_keys == response.json.keys()
182+
# create new versions
183+
files = ["test.txt", "test3.txt", "test.qgs"]
184+
for file in files:
185+
upload_file_to_project(project, file, client)
186+
# project version does not exist
187+
response = client.get(
188+
f"v2/projects/{project.id}?files_at_version=v{project.latest_version+1}"
189+
)
190+
assert response.status_code == 404
191+
# files
192+
response = client.get(
193+
f"v2/projects/{project.id}?files_at_version=v{project.latest_version-2}"
194+
)
195+
assert response.status_code == 200
196+
assert len(response.json["files"]) == 1
197+
assert any(resp_files["path"] == files[0] for resp_files in response.json["files"])
198+
assert not any(
199+
resp_files["path"] == files[1] for resp_files in response.json["files"]
200+
)
201+
response = client.get(
202+
f"v2/projects/{project.id}?files_at_version=v{project.latest_version}"
203+
)
204+
assert len(response.json["files"]) == 3
205+
assert {f["path"] for f in response.json["files"]} == set(files)

0 commit comments

Comments
 (0)