1
+ """
2
+ Tests for LookML constants parsing and substitution.
3
+
4
+ This module tests the constant parsing functionality, including:
5
+ - Parsing constants from LookML files
6
+ - Substituting constants in strings using @{constant_name} syntax
7
+ - Handling constants in views, explores, and their properties
8
+ """
9
+
10
+ import pytest
11
+ import os
12
+ from lkml2cube .parser .loader import file_loader , substitute_constants
13
+
14
+
15
+ class TestConstantParsing :
16
+ """Test constant parsing and substitution functionality."""
17
+
18
+ def test_constant_substitution_simple (self ):
19
+ """Test basic constant substitution in strings."""
20
+ constants = {'city' : 'Tokyo' , 'country' : 'Japan' }
21
+
22
+ # Test simple string substitution
23
+ result = substitute_constants ("@{city} Users" , constants )
24
+ assert result == "Tokyo Users"
25
+
26
+ # Test multiple constants in one string
27
+ result = substitute_constants ("Users from @{city}, @{country}" , constants )
28
+ assert result == "Users from Tokyo, Japan"
29
+
30
+ def test_constant_substitution_in_dict (self ):
31
+ """Test constant substitution in dictionary structures."""
32
+ constants = {'city' : 'Okayama' }
33
+
34
+ obj = {
35
+ 'label' : '@{city} Users' ,
36
+ 'description' : 'Users from @{city}' ,
37
+ 'nested' : {
38
+ 'field' : '@{city} data'
39
+ }
40
+ }
41
+
42
+ result = substitute_constants (obj , constants )
43
+
44
+ assert result ['label' ] == 'Okayama Users'
45
+ assert result ['description' ] == 'Users from Okayama'
46
+ assert result ['nested' ]['field' ] == 'Okayama data'
47
+
48
+ def test_constant_substitution_in_list (self ):
49
+ """Test constant substitution in list structures."""
50
+ constants = {'city' : 'Tokyo' }
51
+
52
+ obj = ['@{city} Users' , '@{city} Orders' , 'Static string' ]
53
+
54
+ result = substitute_constants (obj , constants )
55
+
56
+ assert result [0 ] == 'Tokyo Users'
57
+ assert result [1 ] == 'Tokyo Orders'
58
+ assert result [2 ] == 'Static string'
59
+
60
+ def test_constant_not_found (self ):
61
+ """Test behavior when constant is not found."""
62
+ constants = {'city' : 'Tokyo' }
63
+
64
+ # Should leave unknown constants unchanged
65
+ result = substitute_constants ("@{city} Users from @{unknown}" , constants )
66
+ assert result == "Tokyo Users from @{unknown}"
67
+
68
+ def test_constants_in_lookml_file (self ):
69
+ """Test loading and parsing constants from a LookML file."""
70
+ file_path = os .path .join (os .path .dirname (__file__ ), "samples" , "lkml" , "constants_test.lkml" )
71
+
72
+ # Reset visited_path to ensure clean state
73
+ from lkml2cube .parser .loader import visited_path
74
+ visited_path .clear ()
75
+
76
+ # Load the model
77
+ model = file_loader (file_path , None )
78
+
79
+ # Check that constants were parsed
80
+ assert "constants" in model
81
+ constants_dict = {c ["name" ]: c ["value" ] for c in model ["constants" ]}
82
+ assert "city" in constants_dict
83
+ assert "country" in constants_dict
84
+ assert constants_dict ["city" ] == "Okayama"
85
+ assert constants_dict ["country" ] == "Japan"
86
+
87
+ def test_constant_substitution_in_loaded_model (self ):
88
+ """Test that constants are substituted in loaded LookML model."""
89
+ file_path = os .path .join (os .path .dirname (__file__ ), "samples" , "lkml" , "constants_test.lkml" )
90
+
91
+ # Reset visited_path to ensure clean state
92
+ from lkml2cube .parser .loader import visited_path
93
+ visited_path .clear ()
94
+
95
+ # Load the model
96
+ model = file_loader (file_path , None )
97
+
98
+ # Check that model was loaded
99
+ assert model is not None
100
+
101
+ # Check that constants were substituted in explores
102
+ explores = model .get ("explores" , [])
103
+ assert len (explores ) > 0
104
+
105
+ users_explore = next ((e for e in explores if e ["name" ] == "users" ), None )
106
+ assert users_explore is not None
107
+ assert users_explore ["label" ] == "Okayama Users"
108
+ assert users_explore ["description" ] == "Users from Okayama, Japan"
109
+
110
+ def test_constant_substitution_in_views (self ):
111
+ """Test that constants are substituted in view definitions."""
112
+ file_path = os .path .join (os .path .dirname (__file__ ), "samples" , "lkml" , "constants_test.lkml" )
113
+
114
+ # Reset visited_path to ensure clean state
115
+ from lkml2cube .parser .loader import visited_path
116
+ visited_path .clear ()
117
+
118
+ # Load the model
119
+ model = file_loader (file_path , None )
120
+
121
+ # Check that model was loaded
122
+ assert model is not None
123
+
124
+ # Check that constants were substituted in views
125
+ views = model .get ("views" , [])
126
+ assert len (views ) > 0
127
+
128
+ users_view = next ((v for v in views if v ["name" ] == "users" ), None )
129
+ assert users_view is not None
130
+ assert users_view ["label" ] == "Okayama Users Data"
131
+
132
+ # Check dimension labels
133
+ dimensions = users_view .get ("dimensions" , [])
134
+ name_dimension = next ((d for d in dimensions if d ["name" ] == "name" ), None )
135
+ assert name_dimension is not None
136
+ assert name_dimension ["label" ] == "User Name in Okayama"
137
+
138
+ # Check measure labels
139
+ measures = users_view .get ("measures" , [])
140
+ count_measure = next ((m for m in measures if m ["name" ] == "count" ), None )
141
+ assert count_measure is not None
142
+ assert count_measure ["label" ] == "Count of Okayama Users"
0 commit comments