Skip to content

Commit

Permalink
clone a form
Browse files Browse the repository at this point in the history
  • Loading branch information
srh-sloan committed Jul 19, 2024
1 parent e36189a commit 8d51e37
Show file tree
Hide file tree
Showing 2 changed files with 228 additions and 0 deletions.
39 changes: 39 additions & 0 deletions app/db/queries/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from app.db.models import Form
from app.db.models import Lizt
from app.db.models import Page
from app.db.models.application_config import Section


def get_form_for_component(component: Component) -> Form:
Expand Down Expand Up @@ -73,6 +74,44 @@ def _initiate_cloned_form(to_clone: Form, new_section_id: str) -> Form:
return clone


def _initiate_cloned_section(to_clone: Section, new_round_id: str) -> Form:
clone = Section(**to_clone.as_dict())
clone.round_id = new_round_id
clone.section_id = uuid4()
clone.is_template = False
clone.source_template_id = to_clone.section_id
clone.template_name = None
clone.pages = []
return clone


def clone_single_section(section_id: str, new_round_id=None) -> Section:
section_to_clone: Section = db.session.query(Section).where(Section.section_id == section_id).one_or_none()
clone = _initiate_cloned_section(section_to_clone, new_round_id)

cloned_forms = []
cloned_pages = []
cloned_components = []
# loop through forms in this section and clone each one
for form_to_clone in section_to_clone.forms:
cloned_form = _initiate_cloned_form(form_to_clone, clone.section_id)
# loop through pages in this section and clone each one
for page_to_clone in form_to_clone.pages:
cloned_page = _initiate_cloned_page(page_to_clone, new_form_id=cloned_form.form_id)
cloned_pages.append(cloned_page)
# clone the components on this page
cloned_components.extend(
_initiate_cloned_components_for_page(page_to_clone.components, cloned_page.page_id)
)

cloned_forms.append(cloned_form)

db.session.add_all([clone, *cloned_forms, *cloned_pages, *cloned_components])
db.session.commit()

return clone


def clone_single_form(form_id: str, new_section_id=None) -> Form:
form_to_clone: Form = db.session.query(Form).where(Form.form_id == form_id).one_or_none()
clone = _initiate_cloned_form(form_to_clone, new_section_id)
Expand Down
189 changes: 189 additions & 0 deletions tests/test_clone.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
from app.db.models import ComponentType
from app.db.models import Page
from app.db.models.application_config import Form
from app.db.models.application_config import Section
from app.db.queries.application import _initiate_cloned_component
from app.db.queries.application import _initiate_cloned_form
from app.db.queries.application import _initiate_cloned_page
from app.db.queries.application import _initiate_cloned_section
from app.db.queries.application import clone_multiple_components
from app.db.queries.application import clone_single_component
from app.db.queries.application import clone_single_form
from app.db.queries.application import clone_single_page
from app.db.queries.application import clone_single_section


@pytest.fixture
Expand All @@ -27,6 +30,29 @@ def mock_new_uuid(mocker):
# =====================================================================================================================


def test_initiate_cloned_section(mock_new_uuid):
clone: Section = Section(
section_id="old-id",
name_in_apply_json={"en": "test section 1"},
round_id="old-section-id",
is_template=True,
template_name="Template Section",
)
result: Section = _initiate_cloned_section(to_clone=clone, new_round_id="new-round")
assert result
assert result.section_id == mock_new_uuid

# Check other bits are the same
assert result.name_in_apply_json == clone.name_in_apply_json

# check template settings
assert result.is_template is False
assert result.source_template_id == "old-id"
assert result.template_name is None

assert result.round_id == "new-round"


def test_initiate_cloned_form(mock_new_uuid):
clone: Form = Form(
form_id="old-id",
Expand Down Expand Up @@ -547,3 +573,166 @@ def test_clone_form_with_pages_and_components(seed_dynamic_data, _db):
assert new_page_1.components[0].component_id not in old_component_ids_1
assert new_page_1.components[1].component_id not in old_component_ids_1
assert new_page_2.components[0].component_id not in old_component_ids_2


@pytest.mark.seed_config(
{
"sections": [
Section(
section_id=uuid4(),
name_in_apply_json={"en": "UT Section 1"},
index=2,
)
]
}
)
def test_clone_section_no_forms(seed_dynamic_data, _db):
old_section = _db.session.get(Section, seed_dynamic_data["sections"][0].section_id)
assert old_section

result = clone_single_section(section_id=old_section.section_id, new_round_id=None)
assert result
assert result.section_id != old_section.section_id

cloned_section = _db.session.get(Section, result.section_id)
assert cloned_section
assert len(cloned_section.forms) == 0

old_section_from_db = _db.session.get(Section, old_section.section_id)
assert old_section_from_db


section_id_to_clone = uuid4()
form_id_to_clone = uuid4()
page_id_to_clone_1 = uuid4()
page_id_to_clone_2 = uuid4()


@pytest.mark.seed_config(
{
"sections": [
Section(
section_id=section_id_to_clone,
name_in_apply_json={"en": "UT Section 2"},
index=2,
)
],
"forms": [
Form(
form_id=form_id_to_clone,
section_id=section_id_to_clone,
name_in_apply_json={"en": "UT Form 2"},
section_index=2,
runner_publish_name="ut-form-2",
)
],
"pages": [
Page(
page_id=page_id_to_clone_1,
form_id=form_id_to_clone,
display_path="testing-clone-from-section-1",
is_template=True,
name_in_apply_json={"en": "Clone testing"},
form_index=0,
),
Page(
page_id=page_id_to_clone_2,
form_id=form_id_to_clone,
display_path="testing-clone-from-section-2",
is_template=True,
name_in_apply_json={"en": "Clone testing"},
form_index=0,
),
],
"components": [
Component(
component_id=uuid4(),
page_id=page_id_to_clone_1,
title="Template qustion 1?",
type=ComponentType.YES_NO_FIELD,
page_index=1,
theme_id=None,
theme_index=2,
options={"hideTitle": False, "classes": "test-class"},
runner_component_name="template_question_name_1",
is_template=True,
),
Component(
component_id=uuid4(),
page_id=page_id_to_clone_1,
title="Template qustion 2?",
type=ComponentType.YES_NO_FIELD,
page_index=1,
theme_id=None,
theme_index=2,
options={"hideTitle": False, "classes": "test-class"},
runner_component_name="template_question_name_2",
is_template=True,
),
Component(
component_id=uuid4(),
page_id=page_id_to_clone_2,
title="Template qustion 3?",
type=ComponentType.YES_NO_FIELD,
page_index=1,
theme_id=None,
theme_index=2,
options={"hideTitle": False, "classes": "test-class"},
runner_component_name="template_question_name_3",
is_template=True,
),
],
}
)
def test_clone_section_with_forms(seed_dynamic_data, _db):
old_section = _db.session.get(Section, seed_dynamic_data["sections"][0].section_id)
assert old_section

result = clone_single_section(section_id=old_section.section_id, new_round_id=None)
assert result
assert result.section_id != old_section.section_id

cloned_section = _db.session.get(Section, result.section_id)
assert cloned_section
assert len(cloned_section.forms) == 1

# check the old section still exists
old_section_from_db = _db.session.get(Section, old_section.section_id)
assert old_section_from_db

# validate the form
cloned_form = _db.session.get(Form, cloned_section.forms[0].form_id)
assert cloned_form
assert len(cloned_form.pages) == 2
new_page_id_1 = next(p.page_id for p in cloned_form.pages if p.display_path == "testing-clone-from-section-1")
new_page_id_2 = next(p.page_id for p in cloned_form.pages if p.display_path == "testing-clone-from-section-2")
new_page_1: Page = _db.session.get(Page, new_page_id_1)
new_page_2: Page = _db.session.get(Page, new_page_id_2)

old_form_from_db = _db.session.get(Form, seed_dynamic_data["forms"][0].form_id)
assert old_form_from_db
assert len(old_form_from_db.pages) == 2

# Set old page id 1 and 2 to be the ids of the old pages that correspond to the new
# pages 1 and 2 by matching display path
old_page_id_1 = next(p.page_id for p in old_form_from_db.pages if p.display_path == new_page_1.display_path)
old_page_id_2 = next(p.page_id for p in old_form_from_db.pages if p.display_path == new_page_2.display_path)

assert new_page_id_1 not in [old_page_id_1, old_page_id_2]
assert new_page_id_2 not in [old_page_id_1, old_page_id_2]

# Check pages and components

assert len(new_page_1.components) == 2
assert len(new_page_2.components) == 1

old_page_1 = _db.session.get(Page, old_page_id_1)
old_page_2 = _db.session.get(Page, old_page_id_2)

old_component_ids_1 = [c.component_id for c in old_page_1.components]
old_component_ids_2 = [c.component_id for c in old_page_2.components]

# check the new components are different than the old ones
assert new_page_1.components[0].component_id not in old_component_ids_1
assert new_page_1.components[1].component_id not in old_component_ids_1
assert new_page_2.components[0].component_id not in old_component_ids_2

0 comments on commit 8d51e37

Please sign in to comment.