2424from types import SimpleNamespace
2525from unittest .mock import MagicMock , patch
2626
27+ import numpy as np
28+ import xarray as xr
29+
2730from xcube_cmems .cmems import Cmems
2831
2932
3033class CmemsTest (unittest .TestCase ):
31-
3234 def setUp (self ):
3335 # Setup environment variables for testing
34- os .environ ["COPERNICUS_MARINE_SERVICE_USERNAME" ] = "testuser"
35- os .environ ["COPERNICUS_MARINE_SERVICE_PASSWORD" ] = "testpass"
36+ os .environ ["COPERNICUSMARINE_SERVICE_USERNAME" ] = "testuser"
37+ os .environ ["COPERNICUSMARINE_SERVICE_PASSWORD" ] = "testpass"
38+ self .cmems = Cmems ()
3639
3740 @patch ("xcube_cmems.cmems.cm.describe" )
3841 def test_get_datasets_with_titles (self , mock_describe ):
@@ -49,8 +52,8 @@ def test_get_datasets_with_titles(self, mock_describe):
4952 mock_catalogue = SimpleNamespace (products = [product_a , product_b ])
5053 mock_describe .return_value = mock_catalogue
5154
52- cmems = Cmems ()
53- datasets_info = cmems .get_datasets_with_titles ()
55+ # cmems = Cmems()
56+ datasets_info = self . cmems .get_datasets_with_titles ()
5457
5558 expected = [
5659 {"dataset_id" : "dataset1" , "title" : "Product A - Dataset 1" },
@@ -64,19 +67,58 @@ def test_open_dataset(self, mock_open_dataset):
6467 # Mock the response from cm.open_dataset
6568 mock_dataset = MagicMock ()
6669 mock_open_dataset .return_value = mock_dataset
67- cmems_instance = Cmems ()
68- result = cmems_instance .open_dataset ("dataset1" )
70+ result = self .cmems .open_dataset ("dataset1" )
6971 self .assertEqual (result , mock_dataset )
7072
7173 # Testing with a non-existing dataset
7274 mock_open_dataset .side_effect = KeyError ("Dataset not found" )
73- result = cmems_instance .open_dataset ("non_existing_dataset" )
75+ result = self . cmems .open_dataset ("non_existing_dataset" )
7476 self .assertIsNone (result )
7577
7678 @patch ("click.confirm" , return_value = True )
7779 def test_open_data_for_not_exsiting_dataset (self , mock_confirm ):
78- cmems = Cmems ()
7980 self .assertIsNone (
80- cmems .open_dataset ("dataset-bal-analysis-forecast" "-wav-hourly" ),
81+ self . cmems .open_dataset ("dataset-bal-analysis-forecast" "-wav-hourly" ),
8182 "Expected the method to return None for a " "non-existing dataset" ,
8283 )
84+
85+ def test_to_json_serializable_scalar_types (self ):
86+ assert self .cmems .to_json_serializable (np .int16 (5 )) == 5
87+ assert self .cmems .to_json_serializable (np .bool_ (True )) is True
88+
89+ def test_to_json_serializable_ndarray (self ):
90+ arr = np .array ([1 , 2 , 3 ], dtype = np .int32 )
91+ result = self .cmems .to_json_serializable (arr )
92+ assert result == [1 , 2 , 3 ]
93+ assert isinstance (result , list )
94+
95+ def test_to_json_serializable_nested_structures (self ):
96+ obj = {
97+ "a" : np .int32 (1 ),
98+ "b" : [np .float64 (2.2 ), {"c" : np .bool_ (False )}],
99+ "d" : (np .int8 (4 ),),
100+ }
101+ expected = {"a" : 1 , "b" : [2.2 , {"c" : False }], "d" : [4 ]}
102+ assert self .cmems .to_json_serializable (obj ) == expected
103+
104+ def test_sanitize_attrs_dataset (self ):
105+ data = xr .Dataset (
106+ {
107+ "var1" : xr .DataArray (
108+ np .random .rand (2 , 2 ),
109+ dims = ["x" , "y" ],
110+ attrs = {"int_attr" : np .int16 (10 ), "float_attr" : np .float64 (2.5 )},
111+ )
112+ },
113+ attrs = {"global_attr" : np .bool_ (True )},
114+ )
115+
116+ sanitized = self .cmems .sanitize_attrs (data )
117+
118+ # Ensure all attributes are native Python types
119+ for k , v in sanitized .attrs .items ():
120+ assert isinstance (v , (int , float , bool , str , list , dict ))
121+
122+ for var in sanitized .data_vars :
123+ for k , v in sanitized [var ].attrs .items ():
124+ assert isinstance (v , (int , float , bool , str , list , dict ))
0 commit comments