94
94
in the specified file. The number of occurrences must match the given
95
95
count.
96
96
97
+ * `@count PATH XPATH TEXT COUNT` checks for the occurrence of the given XPath
98
+ with the given text in the specified file. The number of occurrences must
99
+ match the given count.
100
+
97
101
* `@snapshot NAME PATH XPATH` creates a snapshot test named NAME.
98
102
A snapshot test captures a subtree of the DOM, at the location
99
103
determined by the XPath, and compares it to a pre-recorded value
@@ -382,23 +386,25 @@ def check_tree_attr(tree, path, attr, pat, regexp):
382
386
return ret
383
387
384
388
385
- def check_tree_text (tree , path , pat , regexp ):
389
+ # Returns the number of occurences matching the regex (`regexp`) and the text (`pat`).
390
+ def check_tree_text (tree , path , pat , regexp , stop_at_first ):
386
391
path = normalize_xpath (path )
387
- ret = False
392
+ match_count = 0
388
393
try :
389
394
for e in tree .findall (path ):
390
395
try :
391
396
value = flatten (e )
392
397
except KeyError :
393
398
continue
394
399
else :
395
- ret = check_string (value , pat , regexp )
396
- if ret :
397
- break
400
+ if check_string (value , pat , regexp ):
401
+ match_count += 1
402
+ if stop_at_first :
403
+ break
398
404
except Exception :
399
405
print ('Failed to get path "{}"' .format (path ))
400
406
raise
401
- return ret
407
+ return match_count
402
408
403
409
404
410
def get_tree_count (tree , path ):
@@ -518,6 +524,19 @@ def print_err(lineno, context, err, message=None):
518
524
stderr ("\t {}" .format (context ))
519
525
520
526
527
+ def get_nb_matching_elements (cache , c , regexp , stop_at_first ):
528
+ tree = cache .get_tree (c .args [0 ])
529
+ pat , sep , attr = c .args [1 ].partition ('/@' )
530
+ if sep : # attribute
531
+ tree = cache .get_tree (c .args [0 ])
532
+ return check_tree_attr (tree , pat , attr , c .args [2 ], False )
533
+ else : # normalized text
534
+ pat = c .args [1 ]
535
+ if pat .endswith ('/text()' ):
536
+ pat = pat [:- 7 ]
537
+ return check_tree_text (cache .get_tree (c .args [0 ]), pat , c .args [2 ], regexp , stop_at_first )
538
+
539
+
521
540
ERR_COUNT = 0
522
541
523
542
@@ -538,16 +557,7 @@ def check_command(c, cache):
538
557
ret = check_string (cache .get_file (c .args [0 ]), c .args [1 ], regexp )
539
558
elif len (c .args ) == 3 : # @has/matches <path> <pat> <match> = XML tree test
540
559
cerr = "`XPATH PATTERN` did not match"
541
- tree = cache .get_tree (c .args [0 ])
542
- pat , sep , attr = c .args [1 ].partition ('/@' )
543
- if sep : # attribute
544
- tree = cache .get_tree (c .args [0 ])
545
- ret = check_tree_attr (tree , pat , attr , c .args [2 ], regexp )
546
- else : # normalized text
547
- pat = c .args [1 ]
548
- if pat .endswith ('/text()' ):
549
- pat = pat [:- 7 ]
550
- ret = check_tree_text (cache .get_tree (c .args [0 ]), pat , c .args [2 ], regexp )
560
+ ret = get_nb_matching_elements (cache , c , regexp , True ) != 0
551
561
else :
552
562
raise InvalidCheck ('Invalid number of @{} arguments' .format (c .cmd ))
553
563
@@ -557,6 +567,11 @@ def check_command(c, cache):
557
567
found = get_tree_count (cache .get_tree (c .args [0 ]), c .args [1 ])
558
568
cerr = "Expected {} occurrences but found {}" .format (expected , found )
559
569
ret = expected == found
570
+ elif len (c .args ) == 4 : # @count <path> <pat> <text> <count> = count test
571
+ expected = int (c .args [3 ])
572
+ found = get_nb_matching_elements (cache , c , False , False )
573
+ cerr = "Expected {} occurrences but found {}" .format (expected , found )
574
+ ret = found == expected
560
575
else :
561
576
raise InvalidCheck ('Invalid number of @{} arguments' .format (c .cmd ))
562
577
0 commit comments