2020 LearningPackage ,
2121 PublishableEntity ,
2222 PublishLog ,
23+ PublishLogRecord ,
2324)
2425
2526User = get_user_model ()
@@ -937,16 +938,25 @@ def test_simple_publish_log(self) -> None:
937938
938939 def test_publish_all_drafts_sets_direct_true (self ) -> None :
939940 """publish_all_drafts() marks every PublishLogRecord as direct=True."""
940- entity = publishing_api .create_publishable_entity (
941- self .learning_package_1 .id , "direct_entity" ,
941+ entity_1 = publishing_api .create_publishable_entity (
942+ self .learning_package_1 .id , "direct_entity_1" ,
943+ created = self .now , created_by = None ,
944+ )
945+ publishing_api .create_publishable_entity_version (
946+ entity_1 .id , version_num = 1 , title = "Direct Entity 1" ,
947+ created = self .now , created_by = None ,
948+ )
949+ entity_2 = publishing_api .create_publishable_entity (
950+ self .learning_package_1 .id , "direct_entity_2" ,
942951 created = self .now , created_by = None ,
943952 )
944953 publishing_api .create_publishable_entity_version (
945- entity .id , version_num = 1 , title = "Direct Entity" ,
954+ entity_2 .id , version_num = 1 , title = "Direct Entity 2 " ,
946955 created = self .now , created_by = None ,
947956 )
948957 publish_log = publishing_api .publish_all_drafts (self .learning_package_1 .id )
949- assert publish_log .records .get (entity = entity ).direct is True
958+ assert publish_log .records .get (entity = entity_1 ).direct is True
959+ assert publish_log .records .get (entity = entity_2 ).direct is True
950960
951961 def test_publish_from_drafts_sets_direct_true (self ) -> None :
952962 """An explicitly selected entity in publish_from_drafts() gets direct=True."""
@@ -964,6 +974,18 @@ def test_publish_from_drafts_sets_direct_true(self) -> None:
964974 )
965975 assert publish_log .records .get (entity = entity ).direct is True
966976
977+ def test_publish_log_record_direct_defaults_to_false (self ) -> None :
978+ """
979+ New PublishLogRecords default to direct=False (not None).
980+
981+ None is reserved for historical records that pre-date the direct field
982+ (set via the backfill data migration). Records created by the
983+ application—e.g. side-effect records in _create_side_effects_for_change_log()
984+ that don't explicitly set direct—should get False, not None.
985+ """
986+ field = PublishLogRecord ._meta .get_field ('direct' )
987+ assert field .default is False
988+
967989
968990class EntitiesQueryTestCase (TestCase ):
969991 """
@@ -1486,6 +1508,64 @@ def test_direct_field_publishing_container_marks_dependencies_indirect(self) ->
14861508 assert publish_log .records .get (entity = unit .publishable_entity ).direct is True
14871509 assert publish_log .records .get (entity = component ).direct is False
14881510
1511+ def test_direct_field_unit_no_version_change_still_direct_true (self ) -> None :
1512+ """
1513+ Publishing a Unit that has no version change of its own (draft version
1514+ == published version) still marks the Unit's record as direct=True.
1515+
1516+ The user explicitly selected the Unit to publish, so it gets direct=True
1517+ even though the only actual change is in its Component child. The Unit's
1518+ record has old_version == new_version (pure side-effect in terms of
1519+ versioning), but user intent was directed at the Unit.
1520+ """
1521+ component = publishing_api .create_publishable_entity (
1522+ self .learning_package .id , "no_change_component" ,
1523+ created = self .now , created_by = None ,
1524+ )
1525+ component_v1 = publishing_api .create_publishable_entity_version (
1526+ component .id , version_num = 1 , title = "No-change Component" ,
1527+ created = self .now , created_by = None ,
1528+ )
1529+ unit = containers_api .create_container (
1530+ self .learning_package .id , "no_change_unit" ,
1531+ created = self .now , created_by = None , container_cls = TestContainer ,
1532+ )
1533+ unit_v1 = containers_api .create_container_version (
1534+ unit .id , 1 , title = "No-change Unit" , entities = [component ],
1535+ created = self .now , created_by = None ,
1536+ )
1537+ # Initial publish so both Unit and Component have a published version.
1538+ publishing_api .publish_from_drafts (
1539+ self .learning_package .id ,
1540+ Draft .objects .filter (entity = unit .publishable_entity ),
1541+ )
1542+
1543+ # Create a new Component version. The Unit's draft stays at unit_v1,
1544+ # but its dependencies_hash_digest now differs from the published state.
1545+ publishing_api .create_publishable_entity_version (
1546+ component .id , version_num = 2 , title = "No-change Component v2" ,
1547+ created = self .now , created_by = None ,
1548+ )
1549+
1550+ # Publish the Unit explicitly. The Unit has no version change of its
1551+ # own (old_version == new_version == unit_v1).
1552+ publish_log = publishing_api .publish_from_drafts (
1553+ self .learning_package .id ,
1554+ Draft .objects .filter (entity = unit .publishable_entity ),
1555+ )
1556+ unit_record = publish_log .records .get (entity = unit .publishable_entity )
1557+ component_record = publish_log .records .get (entity = component )
1558+
1559+ # User selected the Unit → direct=True despite no version change.
1560+ assert unit_record .direct is True
1561+ assert unit_record .old_version_id == unit_v1 .pk
1562+ assert unit_record .new_version_id == unit_v1 .pk
1563+
1564+ # Component was pulled in as a dependency → direct=False.
1565+ assert component_record .direct is False
1566+ assert component_record .old_version == component_v1
1567+ assert component_record .new_version != component_v1
1568+
14891569 def test_direct_field_publishing_component_marks_parent_indirect (self ) -> None :
14901570 """
14911571 Publishing a Component directly marks the Component as direct=True.
0 commit comments