@@ -51,8 +51,10 @@ def test_compare(self):
5151 assert Conditional .test ('1 > 10' ) is False
5252 assert Conditional .test ('test is test' )
5353 assert Conditional .test ('apple is not banana' )
54- assert Conditional .test ('1 is True' )
55- assert Conditional .test ('0 is True' ) is False
54+ assert Conditional .test ('1 is True' ) is False
55+ assert Conditional .test ('1 == True' )
56+ assert Conditional .test ('0 == True' ) is False
57+ assert Conditional .test ('2 == True' ) is False
5658
5759 def test_exceptions (self ):
5860 with pytest .raises (ConditionalError , match = 'Unknown Condition:' ):
@@ -98,3 +100,245 @@ def test_regex(self):
98100 assert Conditional .test ('hello !~ h[^aeiou]llo' ) is True
99101 assert Conditional .test ('hello123 !~ h.*\\ d+' ) is False
100102 assert Conditional .test ('hello !~ ^h.*o$' ) is False
103+
104+
105+ class TestConditionalStringComparisons :
106+ """Test conditional evaluations with string values"""
107+
108+ def test_string_equality_with_quotes (self ):
109+ """Test string equality: VAR == "hello" """
110+ # When variables are substituted, 'hello' becomes the Name 'hello'
111+ # and "hello" is a Constant string
112+ assert Conditional .test ('hello == "hello"' ) is True
113+ assert Conditional .test ('hello == "world"' ) is False
114+
115+ def test_string_equality_without_quotes (self ):
116+ """Test string equality: VAR == hello (both Names)"""
117+ assert Conditional .test ('hello == hello' ) is True
118+ assert Conditional .test ('hello == world' ) is False
119+
120+ def test_string_inequality (self ):
121+ """Test string inequality: VAR != "hello" """
122+ assert Conditional .test ('hello != "world"' ) is True
123+ assert Conditional .test ('hello != "hello"' ) is False
124+
125+ def test_string_comparison_less_than (self ):
126+ """Test string comparison: VAR < "world" """
127+ assert Conditional .test ('"apple" < "banana"' ) is True
128+ assert Conditional .test ('"zebra" < "apple"' ) is False
129+
130+ def test_string_comparison_greater_than (self ):
131+ """Test string comparison: VAR > "world" """
132+ assert Conditional .test ('"zebra" > "apple"' ) is True
133+ assert Conditional .test ('"apple" > "zebra"' ) is False
134+
135+ def test_string_comparison_less_than_or_equal (self ):
136+ """Test string comparison: VAR <= "world" """
137+ assert Conditional .test ('"apple" <= "banana"' ) is True
138+ assert Conditional .test ('"apple" <= "apple"' ) is True
139+ assert Conditional .test ('"zebra" <= "apple"' ) is False
140+
141+ def test_string_comparison_greater_than_or_equal (self ):
142+ """Test string comparison: VAR >= "world" """
143+ assert Conditional .test ('"zebra" >= "apple"' ) is True
144+ assert Conditional .test ('"zebra" >= "zebra"' ) is True
145+ assert Conditional .test ('"apple" >= "zebra"' ) is False
146+
147+
148+ class TestConditionalIntegerComparisons :
149+ """Test conditional evaluations with integer values"""
150+
151+ def test_integer_equality (self ):
152+ """Test integer equality: VAR == 123"""
153+ assert Conditional .test ('123 == 123' ) is True
154+ assert Conditional .test ('123 == 456' ) is False
155+
156+ def test_integer_inequality (self ):
157+ """Test integer inequality: VAR != 123"""
158+ assert Conditional .test ('123 != 456' ) is True
159+ assert Conditional .test ('123 != 123' ) is False
160+
161+ def test_integer_less_than (self ):
162+ """Test integer comparison: VAR < 100"""
163+ assert Conditional .test ('50 < 100' ) is True
164+ assert Conditional .test ('150 < 100' ) is False
165+
166+ def test_integer_greater_than (self ):
167+ """Test integer comparison: VAR > 100"""
168+ assert Conditional .test ('150 > 100' ) is True
169+ assert Conditional .test ('50 > 100' ) is False
170+
171+ def test_integer_less_than_or_equal (self ):
172+ """Test integer comparison: VAR <= 100"""
173+ assert Conditional .test ('50 <= 100' ) is True
174+ assert Conditional .test ('100 <= 100' ) is True
175+ assert Conditional .test ('150 <= 100' ) is False
176+
177+ def test_integer_greater_than_or_equal (self ):
178+ """Test integer comparison: VAR >= 100"""
179+ assert Conditional .test ('150 >= 100' ) is True
180+ assert Conditional .test ('100 >= 100' ) is True
181+ assert Conditional .test ('50 >= 100' ) is False
182+
183+ def test_integer_boolean_equality (self ):
184+ """Test integer-boolean equality (Python's behavior: 1 == True, 0 == False)"""
185+ assert Conditional .test ('1 == True' ) is True
186+ assert Conditional .test ('0 == False' ) is True
187+ assert Conditional .test ('2 == True' ) is False
188+
189+
190+ class TestConditionalMixedTypes :
191+ """Test conditional evaluations with mixed types"""
192+
193+ def test_string_number_inequality (self ):
194+ """Test that string "123" is not equal to integer 123"""
195+ assert Conditional .test ('"123" == 123' ) is False
196+ assert Conditional .test ('"123" != 123' ) is True
197+
198+ def test_numeric_string_equality (self ):
199+ """Test numeric string equality"""
200+ assert Conditional .test ('"123" == "123"' ) is True
201+ assert Conditional .test ('"123" != "456"' ) is True
202+
203+
204+ class TestConditionalRegex :
205+ """Test conditional regex matching"""
206+
207+ def test_regex_match (self ):
208+ """Test regex match: string =~ pattern"""
209+ assert Conditional .test ('hello =~ h.*o' ) is True
210+ assert Conditional .test ('hello =~ ^hell' ) is True
211+ assert Conditional .test ('hello =~ world' ) is False
212+
213+ def test_regex_not_match (self ):
214+ """Test regex not match: string !~ pattern"""
215+ assert Conditional .test ('hello !~ world' ) is True
216+ assert Conditional .test ('hello !~ ^hell' ) is False
217+
218+ def test_regex_with_numbers (self ):
219+ """Test regex with numeric strings"""
220+ assert Conditional .test ('123 =~ ^[0-9]+$' ) is True
221+ assert Conditional .test ('hello123 =~ [0-9]+' ) is True
222+ assert Conditional .test ('hello =~ ^[0-9]+$' ) is False
223+
224+
225+ class TestConditionalBoolean :
226+ """Test conditional boolean evaluations"""
227+
228+ def test_truthy_variable (self ):
229+ """Test truthy variable evaluation (Names are truthy)"""
230+ assert Conditional .test ('true' ) is True
231+ assert Conditional .test ('True' ) is True
232+
233+ def test_not_operator (self ):
234+ """Test not operator"""
235+ assert Conditional .test ('not False' ) is True
236+ assert Conditional .test ('not True' ) is False
237+
238+ def test_constant_true (self ):
239+ """Test constant True evaluation"""
240+ assert Conditional .test ('True' ) is True
241+
242+ def test_constant_false (self ):
243+ """Test constant False evaluation"""
244+ assert Conditional .test ('False' ) is False
245+
246+ def test_empty_or_none (self ):
247+ """Test empty/None conditions"""
248+ assert Conditional .test (None ) is False
249+ assert Conditional .test ('' ) is False
250+
251+
252+ class TestConditionalIsOperator :
253+ """Test conditional 'is' and 'is not' operators"""
254+
255+ def test_is_operator_with_none (self ):
256+ """Test 'is' operator with None"""
257+ assert Conditional .test ('None is None' ) is True
258+
259+ def test_is_operator_with_names (self ):
260+ """Test 'is' operator with variable names"""
261+ # Note: Names (identifiers) will be compared as strings, not identity
262+ assert Conditional .test ('test is test' ) is True
263+ assert Conditional .test ('apple is banana' ) is False
264+
265+ def test_is_not_operator (self ):
266+ """Test 'is not' operator"""
267+ assert Conditional .test ('apple is not banana' ) is True
268+ assert Conditional .test ('None is not None' ) is False
269+
270+ def test_is_with_different_types (self ):
271+ """Test 'is' with integers (note: small integers are cached in Python)"""
272+ # In Python, 1 is True returns False (different objects)
273+ assert Conditional .test ('1 is True' ) is False # Different ocjects
274+ assert Conditional .test ('1 == True' )
275+
276+
277+ class TestConditionalEdgeCases :
278+ """Test edge cases and error conditions"""
279+
280+ def test_empty_string_equality (self ):
281+ """Test empty string comparisons"""
282+ assert Conditional .test ('"" == ""' ) is True
283+ assert Conditional .test ('"hello" == ""' ) is False
284+
285+ def test_whitespace_in_strings (self ):
286+ """Test strings with whitespace"""
287+ assert Conditional .test ('"hello world" == "hello world"' ) is True
288+ assert Conditional .test ('"hello" == "hello "' ) is False
289+
290+ def test_special_characters_in_strings (self ):
291+ """Test strings with special characters"""
292+ assert Conditional .test ('"hello@world" == "hello@world"' ) is True
293+ assert Conditional .test ('"a-b-c" == "a-b-c"' ) is True
294+
295+
296+ class TestConditionalRealWorldScenarios :
297+ """Test real-world scenarios from the bug report"""
298+
299+ def test_scenario_int_variable (self ):
300+ """Test scenario with VAR_INT == '123'
301+
302+ In the real system, after variable substitution:
303+ - $VAR_INT becomes the value "123"
304+ - The condition "$VAR_INT == 123" becomes "123 == 123" (both integers)
305+ - The condition '$VAR_INT == "123"' becomes '123 == "123"' (int vs string)
306+ """
307+ # After variable substitution, this becomes:
308+ assert Conditional .test ('123 == "123"' ) is False # Different types
309+ assert Conditional .test ('123 == 123' ) is True # Same type
310+ assert Conditional .test ('"123" == "123"' ) is True # Both strings
311+
312+ def test_scenario_str_variable_no_crash (self ):
313+ """Test scenario with VAR_STR == 'hello' - should NOT crash
314+
315+ This is the main bug fix test. Before the fix, comparing a string
316+ variable to a string literal would crash with:
317+ ValueError: invalid literal for int() with base 10: 'hello'
318+ """
319+ # This should not crash anymore - the key test for the bug fix
320+ assert Conditional .test ('hello == "hello"' ) is True
321+ assert Conditional .test ('"hello" == hello' ) is True
322+ assert Conditional .test ('"hello" == "hello"' ) is True
323+
324+ def test_numeric_string_in_variable (self ):
325+ """Test when a variable contains a numeric string"""
326+ # Variable contains "123" as a string
327+ assert Conditional .test ('"123" == "123"' ) is True
328+ assert Conditional .test ('"123" != 123' ) is True # String vs int
329+
330+ def test_original_crash_scenario (self ):
331+ """Test the exact scenario that caused crash
332+
333+ From demo_str.yml:
334+ only_if: $VAR_STR == "hello"
335+
336+ After substitution becomes: hello == "hello"
337+ This would crash with the old code that forced int() conversion
338+ """
339+ # This exact expression caused the crash
340+ try :
341+ result = Conditional .test ('hello == "hello"' )
342+ assert result is True
343+ except ValueError as e :
344+ pytest .fail (f'Should not raise ValueError: { e } ' )
0 commit comments