Skip to content

Commit 79c6526

Browse files
committed
Confluence update_or_create doesn't respect parent_id #956
1 parent be42352 commit 79c6526

3 files changed

Lines changed: 56 additions & 3 deletions

File tree

‎atlassian/confluence/server/__init__.py‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,8 +1887,15 @@ def update_or_create(
18871887
raise ApiValueError("space is required when parent_id is omitted")
18881888
space = self.get_page_space(parent_id)
18891889

1890-
if self.page_exists(space, title):
1891-
page_id = self.get_page_id(space, title)
1890+
# A title is only unique among siblings. Searching the whole space
1891+
# when a parent is supplied could update and move a same-titled page
1892+
# from another branch (#956).
1893+
if parent_id is not None:
1894+
page_id = self.get_descendant_page_id(space, parent_id, title) or None
1895+
else:
1896+
page_id = self.get_page_id(space, title) if self.page_exists(space, title) else None
1897+
1898+
if page_id is not None:
18921899
parent_id = parent_id if parent_id is not None else self.get_parent_content_id(page_id)
18931900
result = self.update_page(
18941901
parent_id=parent_id,

‎docs/confluence.rst‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ Page actions
259259
# Get every contributor for a collaboratively edited page revision.
260260
contributors = confluence.get_page_version_contributors(page_id, version_number)
261261
262-
# Update page or create page if it is not exists. parent_id is optional;
262+
# Update the page only when the title exists under parent_id; a same-titled
263+
# page elsewhere in the space is left untouched. parent_id is optional;
263264
# use a space key to create or update a top-level page.
264265
confluence.update_or_create(parent_id, title, body, representation='storage', full_width=False)
265266
confluence.update_or_create(title=title, body=body, space='SPACEKEY')

‎tests/confluence/test_confluence_server.py‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,51 @@ def test_update_or_create_requires_space_for_a_top_level_page(self, confluence_s
353353
with pytest.raises(ApiValueError, match="space is required"):
354354
confluence_server.update_or_create(title="Top level", body="<p>Body</p>")
355355

356+
@patch.object(ConfluenceServer, "create_page")
357+
@patch.object(ConfluenceServer, "page_exists")
358+
@patch.object(ConfluenceServer, "get_descendant_page_id", return_value="")
359+
def test_update_or_create_creates_when_same_title_is_under_another_parent(
360+
self, mock_descendant_id, mock_page_exists, mock_create_page, confluence_server
361+
):
362+
mock_create_page.return_value = {"id": "new", "_links": {"tinyui": "/x/new"}}
363+
364+
confluence_server.update_or_create("parent-a", "Report", "<p>Body</p>", space="TEAM")
365+
366+
mock_descendant_id.assert_called_once_with("TEAM", "parent-a", "Report")
367+
mock_page_exists.assert_not_called()
368+
mock_create_page.assert_called_once_with(
369+
space="TEAM",
370+
parent_id="parent-a",
371+
title="Report",
372+
body="<p>Body</p>",
373+
representation="storage",
374+
editor=None,
375+
full_width=False,
376+
)
377+
378+
@patch.object(ConfluenceServer, "update_page")
379+
@patch.object(ConfluenceServer, "page_exists")
380+
@patch.object(ConfluenceServer, "get_descendant_page_id", return_value="child-a")
381+
def test_update_or_create_updates_only_the_matching_child(
382+
self, mock_descendant_id, mock_page_exists, mock_update_page, confluence_server
383+
):
384+
mock_update_page.return_value = {"id": "child-a", "_links": {"tinyui": "/x/child"}}
385+
386+
confluence_server.update_or_create("parent-a", "Report", "<p>Body</p>", space="TEAM")
387+
388+
mock_descendant_id.assert_called_once_with("TEAM", "parent-a", "Report")
389+
mock_page_exists.assert_not_called()
390+
mock_update_page.assert_called_once_with(
391+
parent_id="parent-a",
392+
page_id="child-a",
393+
title="Report",
394+
body="<p>Body</p>",
395+
representation="storage",
396+
minor_edit=False,
397+
version_comment=None,
398+
full_width=False,
399+
)
400+
356401
@patch.object(ConfluenceServer, "update_page")
357402
def test_update_existing_page_preserves_confluence_image_storage_markup(self, mock_update_page, confluence_server):
358403
body = '<table><tr><td><ac:image><ri:attachment ri:filename="chart.png" /></ac:image></td></tr></table>'

0 commit comments

Comments
 (0)