Skip to content

Commit 716354e

Browse files
feat: emit a bulk change event when multiple entities are edited at once
1 parent 296b74c commit 716354e

2 files changed

Lines changed: 58 additions & 1 deletion

File tree

src/openedx_content/applets/publishing/api.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from contextlib import nullcontext
1111
from datetime import datetime, timezone
12+
from functools import partial
1213
from typing import ContextManager, Optional, cast
1314

1415
from django.core.exceptions import ObjectDoesNotExist
@@ -1419,5 +1420,6 @@ def bulk_draft_changes_for(
14191420
changed_by=changed_by,
14201421
exit_callbacks=[
14211422
_create_side_effects_for_change_log,
1423+
partial(_emit_event_for_change_log, time_stamp=changed_at, user_id=changed_by),
14221424
]
14231425
)

tests/openedx_content/applets/publishing/test_signals.py

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ def test_single_entity_changed() -> None:
2525
"""
2626
learning_package = api.create_learning_package(key="lp1", title="Test LP 📦")
2727

28-
entity = api.create_publishable_entity(learning_package.id, key="entity1", created=now_time, created_by=None)
28+
# Note: creating an entity does not emit any events until we create a version of that entity.
29+
with capture_events(expected_count=0):
30+
entity = api.create_publishable_entity(learning_package.id, key="entity1", created=now_time, created_by=None)
2931

3032
NEW_VERSION_NUM = 3 # Just for fun let's use a version number other than 1
3133

@@ -70,3 +72,56 @@ def test_single_entity_changed_abort() -> None:
7072
raise DeliberateRollbackException()
7173
except DeliberateRollbackException:
7274
pass
75+
76+
77+
def test_multiple_entites_changed() -> None:
78+
"""
79+
Test that LEARNING_PACKAGE_ENTITIES_CHANGED is emitted when we change
80+
several publishable entities in a single edit.
81+
"""
82+
learning_package = api.create_learning_package(key="lp1", title="Test LP 📦")
83+
84+
# Entity 1 will have no initial version:
85+
entity1 = api.create_publishable_entity(learning_package.id, key="entity1", created=now_time, created_by=None)
86+
# Entity 2 will have an initial version:
87+
entity2 = api.create_publishable_entity(learning_package.id, key="entity2", created=now_time, created_by=None)
88+
api.create_publishable_entity_version(
89+
entity2.id, version_num=1, title="Entity 2 V1", created=now_time, created_by=None
90+
)
91+
# Entity 3 will have an initial version that later gets deleted:
92+
entity3 = api.create_publishable_entity(learning_package.id, key="entity3", created=now_time, created_by=None)
93+
api.create_publishable_entity_version(
94+
entity3.id, version_num=1, title="Entity 3 V1", created=now_time, created_by=None
95+
)
96+
97+
with capture_events(expected_count=1) as captured:
98+
with api.bulk_draft_changes_for(learning_package.id, changed_by=None, changed_at=now_time) as draft_change_log:
99+
# Create two versions of entity1:
100+
api.create_publishable_entity_version(
101+
entity1.id, version_num=1, title="Entity 1 V1", created=now_time, created_by=None
102+
)
103+
api.create_publishable_entity_version(
104+
entity1.id, version_num=2, title="Entity 1 V2", created=now_time, created_by=None
105+
)
106+
# Create a version 2 of entity 2:
107+
api.create_publishable_entity_version(
108+
entity2.id, version_num=2, title="Entity 2 V2", created=now_time, created_by=None
109+
)
110+
# Delete entity 3:
111+
api.set_draft_version(entity3.id, None, set_at=now_time, set_by=None)
112+
113+
event = captured[0]
114+
assert event.signal is api.signals.LEARNING_PACKAGE_ENTITIES_CHANGED
115+
assert event.kwargs["learning_package"].id == learning_package.id
116+
assert event.kwargs["learning_package"].title == "Test LP 📦"
117+
assert event.kwargs["changed_by"].user_id is None
118+
assert event.kwargs["change_log"].draft_change_log_id == draft_change_log.id
119+
assert event.kwargs["change_log"].changes == [
120+
# Entity 1 jumps from no version to version 2:
121+
api.signals.ChangeLogRecordData(entity_id=entity1.id, old_version=None, new_version=2),
122+
# Entity 2 jumps v1 -> v2:
123+
api.signals.ChangeLogRecordData(entity_id=entity2.id, old_version=1, new_version=2),
124+
# Entity 3 gets deleted:
125+
api.signals.ChangeLogRecordData(entity_id=entity3.id, old_version=1, new_version=None),
126+
]
127+
assert event.kwargs["metadata"].time == now_time

0 commit comments

Comments
 (0)