@@ -146,14 +146,11 @@ def test_regex_brackets_empty_brackets():
146146def test_regex_brackets_with_strip_spaces ():
147147 """Test brackets pattern with strip_spaces option"""
148148 text = "Function ( spaced content ) and (normal)"
149- pattern = Regex .brackets (strip_spaces = True )
149+ pattern = Regex .brackets (strip_spaces = True , is_group = True )
150150 matches = rx .findall (pattern , text )
151- assert "( spaced content )" in matches
152- assert "(normal)" in matches
153- pattern = Regex .brackets (strip_spaces = False )
154- matches = rx .findall (pattern , text )
155- assert "( spaced content )" in matches
156- assert "(normal)" in matches
151+ assert len (matches ) == 2
152+ assert any ("spaced content" in m for m in matches )
153+ assert "normal" in matches
157154
158155
159156def test_regex_brackets_as_group ():
@@ -165,6 +162,21 @@ def test_regex_brackets_as_group():
165162 assert match .group (1 ) == "content"
166163
167164
165+ def test_regex_brackets_ignore_in_strings ():
166+ """Test brackets pattern with ignore_in_strings option"""
167+ text = 'func(param = "f(x)")'
168+ pattern = Regex .brackets (ignore_in_strings = True )
169+ matches = rx .findall (pattern , text )
170+ assert len (matches ) == 1
171+ assert 'param = "f(x)"' in matches [0 ]
172+
173+ # TEST THAT IT CORRECTLY HANDLES BRACKETS INSIDE STRINGS
174+ text2 = 'outer("inner(test)")'
175+ matches2 = rx .findall (pattern , text2 )
176+ assert len (matches2 ) == 1
177+ assert 'inner(test)' in matches2 [0 ]
178+
179+
168180def test_regex_outside_strings_pattern ():
169181 """Test outside_strings method returns correct pattern"""
170182 pattern = Regex .outside_strings ()
@@ -178,8 +190,25 @@ def test_regex_outside_strings_custom_pattern():
178190 text = 'Number 123 and "string 456" and 789'
179191 matches = re .findall (pattern , text )
180192 assert "123" in matches
181- assert "789" in matches
182193 assert "456" not in matches
194+ assert "789" in matches
195+
196+
197+ def test_regex_outside_strings_with_special_chars ():
198+ """Test outside_strings with special characters"""
199+ pattern = Regex .outside_strings (r"\$" )
200+ text = 'Price $100 and "cost $50" and $200'
201+ matches = re .findall (pattern , text )
202+ assert len (matches ) >= 2
203+
204+
205+ def test_regex_outside_strings_complex_pattern ():
206+ """Test outside_strings with complex pattern"""
207+ pattern = Regex .outside_strings (r"[a-z]+" )
208+ text = 'word1 "word2" word3 \' word4\' word5'
209+ matches = re .findall (pattern , text )
210+ assert len (matches ) >= 3
211+ assert any ("word" in match for match in matches )
183212
184213
185214def test_regex_all_except_pattern ():
@@ -188,16 +217,32 @@ def test_regex_all_except_pattern():
188217 assert isinstance (pattern , str )
189218
190219
220+ def test_regex_all_except_basic ():
221+ """Test all_except with basic pattern"""
222+ pattern = Regex .all_except (">" )
223+ text = "Hello > World"
224+ match = re .match (pattern , text )
225+ assert match is not None
226+ assert "Hello" in match .group (0 )
227+ assert ">" not in match .group (0 )
228+
229+
191230def test_regex_all_except_with_ignore ():
192231 """Test all_except with ignore pattern"""
193232 pattern = Regex .all_except (">" , "->" )
194- assert isinstance (pattern , str )
233+ text = "Arrow -> here"
234+ match = re .match (pattern , text )
235+ assert match is not None
236+ assert len (match .group (0 )) > 0
195237
196238
197239def test_regex_all_except_as_group ():
198240 """Test all_except with is_group option"""
199241 pattern = Regex .all_except (">" , is_group = True )
200- assert isinstance (pattern , str )
242+ text = "Content > more"
243+ match = re .match (pattern , text )
244+ assert match is not None
245+ assert match .group (1 ) is not None
201246
202247
203248def test_regex_func_call_pattern ():
@@ -232,8 +277,27 @@ def test_regex_rgba_str_default_separator():
232277 """Test rgba_str pattern with default comma separator"""
233278 text = "Color rgba(255, 128, 0) and (100, 200, 50, 0.5)"
234279 pattern = Regex .rgba_str ()
235- matches = re .findall (pattern , text , re . IGNORECASE | re . VERBOSE )
280+ matches = re .findall (pattern , text )
236281 assert len (matches ) > 0
282+ assert len (matches ) >= 2
283+
284+
285+ def test_regex_rgba_str_valid_values ():
286+ """Test rgba_str pattern validates correct ranges"""
287+ pattern = Regex .rgba_str ()
288+ # VALID RGB VALUES IN A STRING
289+ text = "Colors: rgba(255, 255, 255, 1.0) and rgb(0, 0, 0) and (128, 128, 128) and plain 255, 128, 0"
290+ matches = re .findall (pattern , text )
291+ assert len (matches ) >= 4 , f"Should match all valid colors, got: { matches } "
292+
293+ # INVALID RGB VALUES (OUT OF RANGE) SHOULD NOT MATCH OR MATCH PARTIALLY
294+ text_invalid = "Invalid: rgba(256, 128, 0) and rgb(300, 0, 0)"
295+ matches_invalid = re .findall (pattern , text_invalid )
296+ # SHOULD EITHER NOT MATCH OR NOT INCLUDE THE INVALID VALUES
297+ for match in matches_invalid :
298+ match_str = str (match )
299+ assert "256" not in match_str
300+ assert "300" not in match_str
237301
238302
239303def test_regex_rgba_str_no_alpha ():
@@ -259,10 +323,36 @@ def test_regex_hsla_str_default_separator():
259323 """Test hsla_str pattern with default comma separator"""
260324 text = "Color hsla(240, 100%, 50%) and (120, 80%, 60%, 0.8)"
261325 pattern = Regex .hsla_str ()
262- matches = re .findall (pattern , text , re . IGNORECASE | re . VERBOSE )
326+ matches = re .findall (pattern , text )
263327 assert len (matches ) > 0
264328
265329
330+ def test_regex_hsla_str_valid_values ():
331+ """Test hsla_str pattern validates correct ranges"""
332+ pattern = Regex .hsla_str ()
333+ # VALID HSL VALUES IN A STRING
334+ text = "Colors: hsla(360, 100%, 50%, 1.0) and hsl(0, 0%, 0%) and (180, 50%, 50%) and plain 240, 100%, 50% and with degree 120°, 80%, 60%"
335+ matches = re .findall (pattern , text )
336+ assert len (matches ) >= 5 , f"Should match all valid colors, got: { matches } "
337+
338+ # VERIFY THAT % AND ° SYMBOLS ARE NOT IN THE CAPTURED GROUPS
339+ for match in matches :
340+ groups = match if isinstance (match , tuple ) else (match , )
341+ for group in groups :
342+ if group : # Skip empty groups
343+ assert "%" not in group , f"Percent sign should not be in captured group: { group } "
344+ assert "°" not in group , f"Degree sign should not be in captured group: { group } "
345+
346+ # INVALID HSL VALUES (OUT OF RANGE)
347+ text_invalid = "Invalid: hsla(361, 100%, 50%) and hsl(240, 101%, 50%)"
348+ matches_invalid = re .findall (pattern , text_invalid )
349+ # SHOULD EITHER NOT MATCH OR NOT INCLUDE THE INVALID VALUES
350+ for match in matches_invalid :
351+ match_str = str (match )
352+ assert "361" not in match_str
353+ assert "101" not in match_str
354+
355+
266356def test_regex_hsla_str_no_alpha ():
267357 """Test hsla_str pattern with alpha disabled"""
268358 pattern = Regex .hsla_str (allow_alpha = False )
@@ -284,23 +374,89 @@ def test_regex_hexa_str_pattern():
284374def test_regex_hexa_str_with_alpha ():
285375 """Test hexa_str pattern with alpha channel"""
286376 pattern = Regex .hexa_str (allow_alpha = True )
287- test_colors = ["FF0000" , "FF0000FF" , "F00" , "F00F" ]
288- for color in test_colors :
289- assert re .match (pattern , color ) is not None
377+ text = "Colors: FF0000 and FF0000FF and F00 and F00F and #ABCDEF and 0xF0F in text"
378+ matches = re .findall (pattern , text )
379+ assert len (matches ) == 6 , f"Should match all 6 colors, got: { matches } "
380+ # VERIFY ALL EXPECTED COLORS ARE CAPTURED (GROUP 1 CONTAINS THE HEX VALUE)
381+ expected = ["FF0000" , "FF0000FF" , "F00" , "F00F" , "ABCDEF" , "F0F" ]
382+ for exp in expected :
383+ assert any (exp .upper () == match .upper () for match in matches ), f"Should match { exp } "
290384
291385
292386def test_regex_hexa_str_no_alpha ():
293387 """Test hexa_str pattern without alpha channel"""
294388 pattern = Regex .hexa_str (allow_alpha = False )
295- valid_colors = ["FF0000" , "F00" ]
296- invalid_colors = ["FF0000FF" , "F00F" ]
297-
298- for color in valid_colors :
299- match = re .match (pattern , color )
300- assert match is not None
301- assert match .group () == color
302-
303- for color in invalid_colors :
304- match = re .match (pattern , color )
305- if match :
306- assert match .group () != color
389+
390+ # TEST VALID COLORS (3 AND 6 DIGIT FORMATS)
391+ text = "Valid colors: FF0000 and F00 and #ABCDEF and 0xABC in the text"
392+ matches = re .findall (pattern , text )
393+ assert len (matches ) == 4 , f"Should match all 4 valid colors, got: { matches } "
394+ # THE CAPTURED GROUPS SHOULD NOT INCLUDE PREFIX
395+ for hex_value in matches :
396+ assert "#" not in hex_value
397+ assert "0x" not in hex_value .lower ()
398+
399+ # TEST THAT 4-DIGIT AND 8-DIGIT FORMATS ONLY PARTIALLY MATCH (FIRST 3 OR 6 CHARS)
400+ text_with_alpha = "With alpha: FF0000FF and F00F should only match the non-alpha part"
401+ matches_alpha = re .findall (pattern , text_with_alpha )
402+ # SHOULD MATCH FF0000 AND F00 (WITHOUT THE ALPHA CHANNEL)
403+ assert len (matches_alpha ) == 2
404+ for hex_value in matches_alpha :
405+ assert len (hex_value ) in [3 , 6 ], f"Should only match 3 or 6 digit formats, got: { hex_value } "
406+
407+
408+ def test_regex_hexa_str_with_prefix ():
409+ """Test hexa_str pattern with optional prefixes"""
410+ pattern = Regex .hexa_str (allow_alpha = True )
411+ text = "Mixed: #FF0000 and 0xABCDEF and F00 and #F00F in text"
412+ matches = re .findall (pattern , text )
413+ assert len (matches ) == 4 , f"Should match all 4 colors, got: { matches } "
414+
415+ # VERIFY THE CAPTURED HEX VALUES (WITHOUT PREFIX)
416+ expected = ["FF0000" , "ABCDEF" , "F00" , "F00F" ]
417+ for exp in expected :
418+ assert any (exp .upper () == match .upper () for match in matches ), f"Should capture { exp } "
419+
420+
421+ def test_regex_func_call_nested ():
422+ """Test func_call pattern with nested function calls"""
423+ text = "outer(inner(arg1, arg2), arg3)"
424+ pattern = Regex .func_call ()
425+ matches = rx .findall (pattern , text )
426+ assert len (matches ) >= 1
427+ func_names = [m [0 ] for m in matches ]
428+ assert "outer" in func_names
429+
430+
431+ def test_regex_quotes_with_escapes ():
432+ """Test quotes pattern handles escaped characters properly"""
433+ text = r'He said "She said \"Hello\" to me"'
434+ pattern = Regex .quotes ()
435+ matches = rx .findall (pattern , text )
436+ assert len (matches ) >= 1
437+
438+
439+ def test_regex_rgba_str_without_prefix ():
440+ """Test rgba_str matches plain number format"""
441+ pattern = Regex .rgba_str ()
442+ text = "255, 128, 0"
443+ match = re .search (pattern , text )
444+ assert match is not None
445+
446+
447+ def test_regex_hsla_str_without_prefix ():
448+ """Test hsla_str matches plain number format"""
449+ pattern = Regex .hsla_str ()
450+ text = "240, 100%, 50%"
451+ match = re .search (pattern , text )
452+ assert match is not None
453+
454+
455+ def test_regex_brackets_deeply_nested ():
456+ """Test brackets pattern with deeply nested brackets"""
457+ text = "Level1(Level2(Level3(deepest)))"
458+ pattern = Regex .brackets ()
459+ matches = rx .findall (pattern , text )
460+ assert len (matches ) >= 1
461+ assert "deepest" in matches [0 ]
462+ assert "Level2" in matches [0 ]
0 commit comments