@@ -510,27 +510,71 @@ def test_component_with_missing_chart_id(self, orguser, org):
510510class TestUpdateSnapshot :
511511 """Tests for ReportService.update_snapshot"""
512512
513- def test_update_summary (self , sample_snapshot , org ):
513+ def test_update_summary (self , sample_snapshot , org , orguser ):
514514 """Updating 'summary' succeeds"""
515515 data = SnapshotUpdate (summary = "New summary" )
516- updated = ReportService .update_snapshot (sample_snapshot .id , org , data )
516+ updated = ReportService .update_snapshot (sample_snapshot .id , data , orguser )
517517 assert updated .summary == "New summary"
518518
519- def test_update_not_found_raises (self , org ):
519+ def test_update_not_found_raises (self , org , orguser ):
520520 """Updating nonexistent snapshot raises SnapshotNotFoundError"""
521521 data = SnapshotUpdate (summary = "test" )
522522 with pytest .raises (SnapshotNotFoundError ):
523- ReportService .update_snapshot (99999 , org , data )
523+ ReportService .update_snapshot (99999 , data , orguser )
524524
525- def test_update_with_none_value_skips (self , sample_snapshot , org ):
525+ def test_update_with_none_value_skips (self , sample_snapshot , org , orguser ):
526526 """Updating with None value does not change the field"""
527527 sample_snapshot .summary = "Original"
528528 sample_snapshot .save (update_fields = ["summary" ])
529529
530530 data = SnapshotUpdate (summary = None )
531- updated = ReportService .update_snapshot (sample_snapshot .id , org , data )
531+ updated = ReportService .update_snapshot (sample_snapshot .id , data , orguser )
532532 assert updated .summary == "Original"
533533
534+ def test_update_sets_last_modified_by (self , sample_snapshot , org , orguser ):
535+ """Updating summary sets last_modified_by to the editing user"""
536+ assert sample_snapshot .last_modified_by is None
537+
538+ data = SnapshotUpdate (summary = "Edited summary" )
539+ updated = ReportService .update_snapshot (sample_snapshot .id , data , orguser )
540+
541+ assert updated .last_modified_by == orguser
542+ assert updated .last_modified_by .user .email == orguser .user .email
543+
544+ def test_update_tracks_different_modifier (self , sample_snapshot , org , other_orguser ):
545+ """last_modified_by reflects the user who made the latest edit"""
546+ data = SnapshotUpdate (summary = "Edited by other user" )
547+ updated = ReportService .update_snapshot (sample_snapshot .id , data , other_orguser )
548+
549+ assert updated .last_modified_by == other_orguser
550+ assert updated .last_modified_by .user .email == other_orguser .user .email
551+
552+ def test_update_none_summary_does_not_set_last_modified_by (self , sample_snapshot , org , orguser ):
553+ """When summary is None (no change), last_modified_by is not updated"""
554+ assert sample_snapshot .last_modified_by is None
555+
556+ data = SnapshotUpdate (summary = None )
557+ updated = ReportService .update_snapshot (sample_snapshot .id , data , orguser )
558+
559+ assert updated .last_modified_by is None
560+
561+ def test_creator_writes_then_other_user_edits (
562+ self , sample_snapshot , org , orguser , other_orguser
563+ ):
564+ """Creator writes the initial summary, then another user edits it"""
565+ # Creator writes the first summary
566+ data = SnapshotUpdate (summary = "Initial summary by creator" )
567+ updated = ReportService .update_snapshot (sample_snapshot .id , data , orguser )
568+ assert updated .summary == "Initial summary by creator"
569+ assert updated .last_modified_by == orguser
570+
571+ # A different user edits the summary
572+ data = SnapshotUpdate (summary = "Revised by another user" )
573+ updated = ReportService .update_snapshot (sample_snapshot .id , data , other_orguser )
574+ assert updated .summary == "Revised by another user"
575+ assert updated .last_modified_by == other_orguser
576+ assert updated .created_by == orguser # creator unchanged
577+
534578
535579# ================================================================================
536580# Test delete_snapshot
@@ -653,6 +697,32 @@ def test_warehouse_discovered_column_injects_chart_filters(
653697 col_names = [f ["column" ] for f in filters ]
654698 assert "updated_at" in col_names
655699
700+ def test_view_data_includes_last_modified_by_null (
701+ self , mock_org_warehouse_model , mock_factory , sample_snapshot , org
702+ ):
703+ """report_metadata includes last_modified_by as None for unedited snapshots"""
704+ mock_org_warehouse_model .objects .filter .return_value .first .return_value = MagicMock ()
705+ mock_factory .get_warehouse_client .return_value = MagicMock ()
706+
707+ view_data = ReportService .get_snapshot_view_data (sample_snapshot .id , org )
708+ rm = view_data ["report_metadata" ]
709+ assert "last_modified_by" in rm
710+ assert rm ["last_modified_by" ] is None
711+
712+ def test_view_data_includes_last_modified_by_email (
713+ self , mock_org_warehouse_model , mock_factory , sample_snapshot , org , orguser
714+ ):
715+ """report_metadata includes last_modified_by email after an update"""
716+ mock_org_warehouse_model .objects .filter .return_value .first .return_value = MagicMock ()
717+ mock_factory .get_warehouse_client .return_value = MagicMock ()
718+
719+ data = SnapshotUpdate (summary = "Updated summary" )
720+ ReportService .update_snapshot (sample_snapshot .id , data , orguser )
721+
722+ view_data = ReportService .get_snapshot_view_data (sample_snapshot .id , org )
723+ rm = view_data ["report_metadata" ]
724+ assert rm ["last_modified_by" ] == orguser .user .email
725+
656726 def test_not_found (self , mock_org_warehouse_model , mock_factory , org ):
657727 """Viewing nonexistent snapshot raises SnapshotNotFoundError"""
658728 with pytest .raises (SnapshotNotFoundError ):
0 commit comments