| 
									
										
										
										
											2025-06-06 16:28:28 +09:00
										 |  |  | import pathlib | 
					
						
							|  |  |  | import re | 
					
						
							|  |  |  | from datetime import datetime | 
					
						
							|  |  |  | from unittest import mock | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import pytest | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-23 07:07:52 -07:00
										 |  |  | from datahub.emitter import mce_builder | 
					
						
							| 
									
										
										
										
											2025-06-06 16:28:28 +09:00
										 |  |  | from datahub.errors import ItemNotFoundError | 
					
						
							|  |  |  | from datahub.metadata.urns import ( | 
					
						
							|  |  |  |     ChartUrn, | 
					
						
							|  |  |  |     CorpUserUrn, | 
					
						
							|  |  |  |     DashboardUrn, | 
					
						
							|  |  |  |     DatasetUrn, | 
					
						
							|  |  |  |     DomainUrn, | 
					
						
							|  |  |  |     GlossaryTermUrn, | 
					
						
							|  |  |  |     TagUrn, | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | from datahub.sdk.dashboard import Dashboard | 
					
						
							|  |  |  | from datahub.testing.sdk_v2_helpers import assert_entity_golden | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _GOLDEN_DIR = pathlib.Path(__file__).parent / "dashboard_golden" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_dashboard_basic(pytestconfig: pytest.Config) -> None: | 
					
						
							|  |  |  |     d = Dashboard( | 
					
						
							|  |  |  |         platform="looker", | 
					
						
							|  |  |  |         name="example_dashboard", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Check urn setup. | 
					
						
							|  |  |  |     assert Dashboard.get_urn_type() == DashboardUrn | 
					
						
							|  |  |  |     assert isinstance(d.urn, DashboardUrn) | 
					
						
							|  |  |  |     assert str(d.urn) == "urn:li:dashboard:(looker,example_dashboard)" | 
					
						
							|  |  |  |     assert str(d.urn) in repr(d) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Check most attributes. | 
					
						
							|  |  |  |     assert d.platform is not None | 
					
						
							|  |  |  |     assert d.platform.platform_name == "looker" | 
					
						
							|  |  |  |     assert d.platform_instance is None | 
					
						
							|  |  |  |     assert d.tags is None | 
					
						
							|  |  |  |     assert d.terms is None | 
					
						
							|  |  |  |     assert d.last_modified is None | 
					
						
							| 
									
										
										
										
											2025-09-03 12:36:07 -07:00
										 |  |  |     assert d.description is None | 
					
						
							| 
									
										
										
										
											2025-06-06 16:28:28 +09:00
										 |  |  |     assert d.custom_properties == {} | 
					
						
							|  |  |  |     assert d.domain is None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(AttributeError): | 
					
						
							|  |  |  |         assert d.extra_attribute  # type: ignore | 
					
						
							|  |  |  |     with pytest.raises(AttributeError): | 
					
						
							|  |  |  |         d.extra_attribute = "slots should reject extra fields"  # type: ignore | 
					
						
							|  |  |  |     with pytest.raises(AttributeError): | 
					
						
							|  |  |  |         # This should fail. Eventually we should make it suggest calling set_owners instead. | 
					
						
							|  |  |  |         d.owners = []  # type: ignore | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert_entity_golden(d, _GOLDEN_DIR / "test_dashboard_basic_golden.json") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_dashboard_complex() -> None: | 
					
						
							|  |  |  |     updated = datetime(2025, 1, 9, 12, 4, 6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     d = Dashboard( | 
					
						
							|  |  |  |         platform="looker", | 
					
						
							|  |  |  |         platform_instance="my_instance", | 
					
						
							|  |  |  |         name="example_dashboard", | 
					
						
							|  |  |  |         display_name="Example Dashboard", | 
					
						
							|  |  |  |         last_modified=updated, | 
					
						
							|  |  |  |         last_refreshed=updated, | 
					
						
							|  |  |  |         custom_properties={ | 
					
						
							|  |  |  |             "key1": "value1", | 
					
						
							|  |  |  |             "key2": "value2", | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         description="Test dashboard", | 
					
						
							|  |  |  |         external_url="https://example.com", | 
					
						
							|  |  |  |         dashboard_url="https://looker.example.com/dashboards/123", | 
					
						
							|  |  |  |         owners=[ | 
					
						
							|  |  |  |             CorpUserUrn("admin@datahubproject.io"), | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         links=[ | 
					
						
							|  |  |  |             "https://example.com/doc1", | 
					
						
							|  |  |  |             ("https://example.com/doc2", "Documentation 2"), | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         tags=[ | 
					
						
							|  |  |  |             TagUrn("tag1"), | 
					
						
							|  |  |  |             TagUrn("tag2"), | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         terms=[ | 
					
						
							|  |  |  |             GlossaryTermUrn("Dashboard"), | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         domain=DomainUrn("Analytics"), | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert d.platform is not None | 
					
						
							|  |  |  |     assert d.platform.platform_name == "looker" | 
					
						
							|  |  |  |     assert d.platform_instance is not None | 
					
						
							|  |  |  |     assert ( | 
					
						
							|  |  |  |         str(d.platform_instance) | 
					
						
							|  |  |  |         == "urn:li:dataPlatformInstance:(urn:li:dataPlatform:looker,my_instance)" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Properties. | 
					
						
							|  |  |  |     assert d.description == "Test dashboard" | 
					
						
							|  |  |  |     assert d.display_name == "Example Dashboard" | 
					
						
							|  |  |  |     assert d.external_url == "https://example.com" | 
					
						
							|  |  |  |     assert d.dashboard_url == "https://looker.example.com/dashboards/123" | 
					
						
							|  |  |  |     assert d.last_modified == updated | 
					
						
							|  |  |  |     assert d.last_refreshed == updated | 
					
						
							|  |  |  |     assert d.custom_properties == {"key1": "value1", "key2": "value2"} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Check standard aspects. | 
					
						
							|  |  |  |     assert d.owners is not None and len(d.owners) == 1 | 
					
						
							|  |  |  |     assert d.links is not None and len(d.links) == 2 | 
					
						
							|  |  |  |     assert d.tags is not None and len(d.tags) == 2 | 
					
						
							|  |  |  |     assert d.terms is not None and len(d.terms) == 1 | 
					
						
							|  |  |  |     assert d.domain == DomainUrn("Analytics") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Add assertions for links | 
					
						
							|  |  |  |     assert d.links is not None | 
					
						
							|  |  |  |     assert len(d.links) == 2 | 
					
						
							|  |  |  |     assert d.links[0].url == "https://example.com/doc1" | 
					
						
							|  |  |  |     assert d.links[1].url == "https://example.com/doc2" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Test chart and dataset operations | 
					
						
							|  |  |  |     d.add_chart("urn:li:chart:(looker,chart1)") | 
					
						
							|  |  |  |     d.add_chart("urn:li:chart:(looker,chart2)") | 
					
						
							|  |  |  |     d.add_input_dataset("urn:li:dataset:(urn:li:dataPlatform:snowflake,my_table,PROD)") | 
					
						
							|  |  |  |     d.add_input_dataset("urn:li:dataset:(urn:li:dataPlatform:snowflake,my_table2,PROD)") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert d.charts == [ | 
					
						
							|  |  |  |         ChartUrn("looker", "chart1"), | 
					
						
							|  |  |  |         ChartUrn("looker", "chart2"), | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     assert d.input_datasets == [ | 
					
						
							|  |  |  |         DatasetUrn(platform="snowflake", name="my_table", env="PROD"), | 
					
						
							|  |  |  |         DatasetUrn(platform="snowflake", name="my_table2", env="PROD"), | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     d.remove_chart("urn:li:chart:(looker,chart1)") | 
					
						
							|  |  |  |     d.remove_input_dataset( | 
					
						
							|  |  |  |         "urn:li:dataset:(urn:li:dataPlatform:snowflake,my_table,PROD)" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert d.charts == [ChartUrn("looker", "chart2")] | 
					
						
							|  |  |  |     assert d.input_datasets == [ | 
					
						
							|  |  |  |         DatasetUrn(platform="snowflake", name="my_table2", env="PROD") | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert_entity_golden( | 
					
						
							|  |  |  |         d, _GOLDEN_DIR / "test_dashboard_complex_golden.json", ["lastRefreshed"] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_client_get_dashboard() -> None: | 
					
						
							|  |  |  |     """Test retrieving Dashboards using client.entities.get().""" | 
					
						
							|  |  |  |     # Set up mock | 
					
						
							|  |  |  |     mock_client = mock.MagicMock() | 
					
						
							|  |  |  |     mock_entities = mock.MagicMock() | 
					
						
							|  |  |  |     mock_client.entities = mock_entities | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Basic retrieval | 
					
						
							|  |  |  |     dashboard_urn = DashboardUrn("looker", "test_dashboard") | 
					
						
							|  |  |  |     expected_dashboard = Dashboard( | 
					
						
							|  |  |  |         platform="looker", | 
					
						
							|  |  |  |         name="test_dashboard", | 
					
						
							|  |  |  |         description="A test dashboard", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     mock_entities.get.return_value = expected_dashboard | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = mock_client.entities.get(dashboard_urn) | 
					
						
							|  |  |  |     assert result == expected_dashboard | 
					
						
							|  |  |  |     mock_entities.get.assert_called_once_with(dashboard_urn) | 
					
						
							|  |  |  |     mock_entities.get.reset_mock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # String URN | 
					
						
							|  |  |  |     urn_str = "urn:li:dashboard:(looker,string_dashboard,prod)" | 
					
						
							|  |  |  |     mock_entities.get.return_value = Dashboard( | 
					
						
							|  |  |  |         platform="looker", name="string_dashboard" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     result = mock_client.entities.get(urn_str) | 
					
						
							|  |  |  |     mock_entities.get.assert_called_once_with(urn_str) | 
					
						
							|  |  |  |     mock_entities.get.reset_mock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Complex dashboard with properties | 
					
						
							|  |  |  |     test_date = datetime(2023, 1, 1, 12, 0, 0) | 
					
						
							|  |  |  |     complex_dashboard = Dashboard( | 
					
						
							|  |  |  |         platform="looker", | 
					
						
							|  |  |  |         name="complex_dashboard", | 
					
						
							|  |  |  |         description="Complex test dashboard", | 
					
						
							|  |  |  |         display_name="My Complex Dashboard", | 
					
						
							|  |  |  |         external_url="https://example.com/dashboard", | 
					
						
							|  |  |  |         dashboard_url="https://looker.example.com/dashboards/456", | 
					
						
							|  |  |  |         last_modified=test_date, | 
					
						
							|  |  |  |         last_refreshed=datetime(2023, 1, 1, 12, 0, 0), | 
					
						
							|  |  |  |         custom_properties={"env": "production", "owner_team": "analytics"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Set relationships and tags | 
					
						
							|  |  |  |     complex_dashboard.set_tags([TagUrn("important"), TagUrn("analytics")]) | 
					
						
							|  |  |  |     complex_dashboard.set_domain(DomainUrn("Analytics")) | 
					
						
							|  |  |  |     complex_dashboard.set_owners([CorpUserUrn("john@example.com")]) | 
					
						
							|  |  |  |     complex_dashboard.add_chart("urn:li:chart:(looker,chart1)") | 
					
						
							|  |  |  |     complex_dashboard.add_input_dataset( | 
					
						
							|  |  |  |         "urn:li:dataset:(urn:li:dataPlatform:snowflake,my_table,PROD)" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     dashboard_urn = DashboardUrn("looker", "complex_dashboard") | 
					
						
							|  |  |  |     mock_entities.get.return_value = complex_dashboard | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = mock_client.entities.get(dashboard_urn) | 
					
						
							|  |  |  |     assert result.name == "complex_dashboard" | 
					
						
							|  |  |  |     assert result.display_name == "My Complex Dashboard" | 
					
						
							|  |  |  |     assert result.last_modified == test_date | 
					
						
							|  |  |  |     assert result.description == "Complex test dashboard" | 
					
						
							|  |  |  |     assert result.dashboard_url == "https://looker.example.com/dashboards/456" | 
					
						
							|  |  |  |     assert result.last_refreshed == datetime(2023, 1, 1, 12, 0, 0) | 
					
						
							|  |  |  |     assert result.tags is not None | 
					
						
							|  |  |  |     assert result.domain is not None | 
					
						
							|  |  |  |     assert result.owners is not None | 
					
						
							|  |  |  |     assert result.charts == [ChartUrn("looker", "chart1")] | 
					
						
							|  |  |  |     assert result.input_datasets == [ | 
					
						
							|  |  |  |         DatasetUrn(platform="snowflake", name="my_table", env="PROD") | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     mock_entities.get.assert_called_once_with(dashboard_urn) | 
					
						
							|  |  |  |     mock_entities.get.reset_mock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Not found case | 
					
						
							|  |  |  |     error_message = f"Entity {dashboard_urn} not found" | 
					
						
							|  |  |  |     mock_entities.get.side_effect = ItemNotFoundError(error_message) | 
					
						
							|  |  |  |     with pytest.raises(ItemNotFoundError, match=re.escape(error_message)): | 
					
						
							|  |  |  |         mock_client.entities.get(dashboard_urn) | 
					
						
							| 
									
										
										
										
											2025-09-23 07:07:52 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_dashboard_audit_stamps() -> None: | 
					
						
							|  |  |  |     """Test HasAuditStamps mixin functionality on Dashboard.""" | 
					
						
							|  |  |  |     created_time = datetime(2023, 1, 1, 10, 0, 0) | 
					
						
							|  |  |  |     modified_time = datetime(2023, 1, 2, 14, 30, 0) | 
					
						
							|  |  |  |     deleted_time = datetime(2023, 1, 3, 16, 45, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Test initialization with audit stamps | 
					
						
							|  |  |  |     d = Dashboard( | 
					
						
							|  |  |  |         platform="looker", | 
					
						
							|  |  |  |         name="audit_test_dashboard", | 
					
						
							|  |  |  |         created_at=created_time, | 
					
						
							|  |  |  |         created_by="creator@example.com", | 
					
						
							|  |  |  |         last_modified=modified_time, | 
					
						
							|  |  |  |         last_modified_by="modifier@example.com", | 
					
						
							|  |  |  |         deleted_on=deleted_time, | 
					
						
							|  |  |  |         deleted_by="deleter@example.com", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Test created_at and created_by | 
					
						
							|  |  |  |     assert d.created_at == created_time | 
					
						
							|  |  |  |     assert d.created_by == "urn:li:corpuser:creator@example.com" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Test last_modified and last_modified_by | 
					
						
							|  |  |  |     assert d.last_modified == modified_time | 
					
						
							|  |  |  |     assert d.last_modified_by == "urn:li:corpuser:modifier@example.com" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Test deleted_on and deleted_by | 
					
						
							|  |  |  |     assert d.deleted_on == deleted_time | 
					
						
							|  |  |  |     assert d.deleted_by == "urn:li:corpuser:deleter@example.com" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_dashboard_audit_stamps_setters() -> None: | 
					
						
							|  |  |  |     """Test setting audit stamps after initialization.""" | 
					
						
							|  |  |  |     d = Dashboard( | 
					
						
							|  |  |  |         platform="looker", | 
					
						
							|  |  |  |         name="audit_setter_test_dashboard", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Initially all should be None | 
					
						
							|  |  |  |     assert d.created_at is None | 
					
						
							|  |  |  |     assert d.created_by is None | 
					
						
							|  |  |  |     assert d.last_modified is None | 
					
						
							|  |  |  |     assert d.last_modified_by is None | 
					
						
							|  |  |  |     assert d.deleted_on is None | 
					
						
							|  |  |  |     assert d.deleted_by is None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Test setting timestamps | 
					
						
							|  |  |  |     created_time = datetime(2023, 1, 1, 10, 0, 0) | 
					
						
							|  |  |  |     modified_time = datetime(2023, 1, 2, 14, 30, 0) | 
					
						
							|  |  |  |     deleted_time = datetime(2023, 1, 3, 16, 45, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     d.set_created_at(created_time) | 
					
						
							|  |  |  |     d.set_last_modified(modified_time) | 
					
						
							|  |  |  |     d.set_deleted_on(deleted_time) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert d.created_at == created_time | 
					
						
							|  |  |  |     assert d.last_modified == modified_time | 
					
						
							|  |  |  |     assert d.deleted_on == deleted_time | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Test setting actors with string URNs | 
					
						
							|  |  |  |     d.set_created_by("creator@example.com") | 
					
						
							|  |  |  |     d.set_last_modified_by("modifier@example.com") | 
					
						
							|  |  |  |     d.set_deleted_by("deleter@example.com") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert d.created_by == "urn:li:corpuser:creator@example.com" | 
					
						
							|  |  |  |     assert d.last_modified_by == "urn:li:corpuser:modifier@example.com" | 
					
						
							|  |  |  |     assert d.deleted_by == "urn:li:corpuser:deleter@example.com" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Test setting actors with CorpUserUrn objects | 
					
						
							|  |  |  |     from datahub.metadata.urns import CorpUserUrn | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     creator_urn = CorpUserUrn("creator_urn@example.com") | 
					
						
							|  |  |  |     modifier_urn = CorpUserUrn("modifier_urn@example.com") | 
					
						
							|  |  |  |     deleter_urn = CorpUserUrn("deleter_urn@example.com") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     d.set_created_by(creator_urn) | 
					
						
							|  |  |  |     d.set_last_modified_by(modifier_urn) | 
					
						
							|  |  |  |     d.set_deleted_by(deleter_urn) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert d.created_by == str(creator_urn) | 
					
						
							|  |  |  |     assert d.last_modified_by == str(modifier_urn) | 
					
						
							|  |  |  |     assert d.deleted_by == str(deleter_urn) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_dashboard_audit_stamps_edge_cases() -> None: | 
					
						
							|  |  |  |     """Test edge cases for audit stamps - setting None values""" | 
					
						
							|  |  |  |     d = Dashboard( | 
					
						
							|  |  |  |         platform="looker", | 
					
						
							|  |  |  |         name="audit_edge_case_dashboard", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # These should not raise errors and should set to None or default values | 
					
						
							|  |  |  |     assert d.created_by is None | 
					
						
							|  |  |  |     assert d.last_modified_by is None | 
					
						
							|  |  |  |     assert d.deleted_by is None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Internally it should have the default values | 
					
						
							|  |  |  |     assert d._get_audit_stamps().created.actor == mce_builder.UNKNOWN_USER | 
					
						
							|  |  |  |     assert d._get_audit_stamps().lastModified.actor == mce_builder.UNKNOWN_USER | 
					
						
							|  |  |  |     assert ( | 
					
						
							|  |  |  |         d._get_audit_stamps().deleted is None | 
					
						
							|  |  |  |     )  # deleted has no default value as per the pdl | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert d.created_at is None | 
					
						
							|  |  |  |     assert d.last_modified is None | 
					
						
							|  |  |  |     assert d.deleted_on is None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Internally it should have the default values | 
					
						
							|  |  |  |     assert d._get_audit_stamps().created.time == 0 | 
					
						
							|  |  |  |     assert d._get_audit_stamps().lastModified.time == 0 | 
					
						
							|  |  |  |     assert ( | 
					
						
							|  |  |  |         d._get_audit_stamps().deleted is None | 
					
						
							|  |  |  |     )  # deleted has no default value as per the pdl | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Test that timestamps are properly converted | 
					
						
							|  |  |  |     test_time = datetime(2023, 1, 1, 12, 0, 0) | 
					
						
							|  |  |  |     d.set_created_at(test_time) | 
					
						
							|  |  |  |     d.set_last_modified(test_time) | 
					
						
							|  |  |  |     d.set_deleted_on(test_time) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Verify the timestamps are stored correctly | 
					
						
							|  |  |  |     assert d.created_at == test_time | 
					
						
							|  |  |  |     assert d.last_modified == test_time | 
					
						
							|  |  |  |     assert d.deleted_on == test_time | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert d._get_audit_stamps().created.time == mce_builder.make_ts_millis(test_time) | 
					
						
							|  |  |  |     assert d._get_audit_stamps().lastModified.time == mce_builder.make_ts_millis( | 
					
						
							|  |  |  |         test_time | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     # deleted should not be None after setting deleted_on | 
					
						
							|  |  |  |     deleted_stamp = d._get_audit_stamps().deleted | 
					
						
							|  |  |  |     assert deleted_stamp is not None | 
					
						
							|  |  |  |     assert deleted_stamp.time == mce_builder.make_ts_millis(test_time) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_dashboard_audit_stamps_integration() -> None: | 
					
						
							|  |  |  |     """Test audit stamps integration with other dashboard functionality.""" | 
					
						
							|  |  |  |     created_time = datetime(2023, 1, 1, 10, 0, 0) | 
					
						
							|  |  |  |     modified_time = datetime(2023, 1, 2, 14, 30, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     d = Dashboard( | 
					
						
							|  |  |  |         platform="looker", | 
					
						
							|  |  |  |         name="audit_integration_dashboard", | 
					
						
							|  |  |  |         display_name="Audit Integration Test", | 
					
						
							|  |  |  |         description="Testing audit stamps with other features", | 
					
						
							|  |  |  |         created_at=created_time, | 
					
						
							|  |  |  |         created_by="creator@example.com", | 
					
						
							|  |  |  |         last_modified=modified_time, | 
					
						
							|  |  |  |         last_modified_by="modifier@example.com", | 
					
						
							|  |  |  |         owners=[CorpUserUrn("owner@example.com")], | 
					
						
							|  |  |  |         tags=[TagUrn("test")], | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Verify audit stamps work alongside other properties | 
					
						
							|  |  |  |     assert d.created_at == created_time | 
					
						
							|  |  |  |     assert d.created_by == "urn:li:corpuser:creator@example.com" | 
					
						
							|  |  |  |     assert d.last_modified == modified_time | 
					
						
							|  |  |  |     assert d.last_modified_by == "urn:li:corpuser:modifier@example.com" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Verify other properties still work | 
					
						
							|  |  |  |     assert d.display_name == "Audit Integration Test" | 
					
						
							|  |  |  |     assert d.description == "Testing audit stamps with other features" | 
					
						
							|  |  |  |     assert d.owners is not None | 
					
						
							|  |  |  |     assert d.tags is not None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Test that modifying audit stamps doesn't affect other properties | 
					
						
							|  |  |  |     new_modified_time = datetime(2023, 1, 3, 16, 0, 0) | 
					
						
							|  |  |  |     d.set_last_modified(new_modified_time) | 
					
						
							|  |  |  |     d.set_last_modified_by("new_modifier@example.com") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert d.last_modified == new_modified_time | 
					
						
							|  |  |  |     assert d.last_modified_by == "urn:li:corpuser:new_modifier@example.com" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Other properties should remain unchanged | 
					
						
							|  |  |  |     assert d.display_name == "Audit Integration Test" | 
					
						
							|  |  |  |     assert d.description == "Testing audit stamps with other features" | 
					
						
							|  |  |  |     assert d.owners is not None | 
					
						
							|  |  |  |     assert d.tags is not None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_dashboard_audit_stamps_golden() -> None: | 
					
						
							|  |  |  |     """Test audit stamps with golden file comparison.""" | 
					
						
							|  |  |  |     created_time = datetime(2023, 1, 1, 10, 0, 0) | 
					
						
							|  |  |  |     modified_time = datetime(2023, 1, 2, 14, 30, 0) | 
					
						
							|  |  |  |     deleted_time = datetime(2023, 1, 3, 16, 45, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     d = Dashboard( | 
					
						
							|  |  |  |         platform="looker", | 
					
						
							|  |  |  |         name="audit_golden_dashboard", | 
					
						
							|  |  |  |         display_name="Audit Golden Test", | 
					
						
							|  |  |  |         description="Testing audit stamps with golden files", | 
					
						
							|  |  |  |         created_at=created_time, | 
					
						
							|  |  |  |         created_by="creator@example.com", | 
					
						
							|  |  |  |         last_modified=modified_time, | 
					
						
							|  |  |  |         last_modified_by="modifier@example.com", | 
					
						
							|  |  |  |         deleted_on=deleted_time, | 
					
						
							|  |  |  |         deleted_by="deleter@example.com", | 
					
						
							|  |  |  |         owners=[CorpUserUrn("owner@example.com")], | 
					
						
							|  |  |  |         tags=[TagUrn("audit"), TagUrn("test")], | 
					
						
							|  |  |  |         custom_properties={"audit_test": "true"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Generate golden file for audit stamps functionality | 
					
						
							|  |  |  |     assert_entity_golden( | 
					
						
							|  |  |  |         d, | 
					
						
							|  |  |  |         _GOLDEN_DIR / "test_dashboard_audit_stamps_golden.json", | 
					
						
							|  |  |  |         ["lastRefreshed"],  # Exclude timestamp fields that might vary between test runs | 
					
						
							|  |  |  |     ) |