@@ -1026,12 +1026,38 @@ def test_graph_sat_size_badges_finish_promptly_after_routes_arrive(self):
10261026 expect (self .page .locator ('.path' ).first .locator ('.size' )).to_contain_text ('n' )
10271027
10281028 def test_graph_unavailable_parameters_keep_size_badges_unknown (self ):
1029+ # Keep unavailable-field UI coverage independent of improvements to registry bounds.
1030+ nodes = [{'name' : name , 'category' : 'formula' , 'variant' : {}, 'default' : True }
1031+ for name in ['Satisfiability' , 'QUBO' ]]
1032+ known = {'certificate' : 'num_vars^3' , 'accuracy' : {'kind' : 'upper_bound' }}
1033+ unavailable = {'certificate' : None , 'accuracy' : {'kind' : 'unavailable' ,
1034+ 'reason' : {'kind' : 'unavailable' , 'detail' : 'Synthetic unavailable parameter' }}}
1035+ fields = {'num_vars' : known , 'num_quadratic_terms' : unavailable }
1036+ scene = {'nodes' : nodes , 'edges' : [{'source' : 0 , 'target' : 1 , 'witness' : True ,
1037+ 'aggregate' : False , 'turing' : False , 'fields' : fields }], 'aliases' : {},
1038+ 'layout' : {'Satisfiability' : {'x' : 0 , 'y' : 0 }, 'QUBO' : {'x' : 100 , 'y' : 70 }}}
1039+ self .page .route ('**/graph-scene.json.gz' , lambda route : route .fulfill (
1040+ body = gzip .compress (json .dumps (scene ).encode ()), content_type = 'application/gzip' ))
1041+ endpoint = lambda i : {'name' : nodes [i ]['name' ], 'variant' : {}}
1042+ paths = {'truncated' : False , 'paths' : [{'steps' : 1 ,
1043+ 'path' : [{'from' : endpoint (0 ), 'to' : endpoint (1 )}]}]}
1044+ comparison = {'profiles' : [{'source_coordinates' : ['num_vars' ], 'fields' : fields }],
1045+ 'front' : [1 ], 'counts' : {'Dominated' : 0 , 'Equivalent' : 0 , 'Incomparable' : 0 , 'Unknown' : 0 }}
1046+ worker = 'self.onmessage = () => {' + '' .join ('self.postMessage(' + json .dumps (reply ) + ');'
1047+ for reply in [{'phase' : 'paths' , 'result' : paths }, {'phase' : 'comparison' , 'result' : comparison }]) + '};'
1048+ self .page .route ('**/path-worker.js' , lambda route : route .fulfill (body = worker , content_type = 'text/javascript' ))
10291049 self .page .goto (self .base + 'graph.html#directions' )
1030- self .choose_endpoint ('source' , 'MVC' )
1031- self .page .locator ('#source-options [aria-label="weight"]' ).get_by_role ('button' , name = 'One' , exact = True ).click ()
1032- self .choose_endpoint ('target' , 'LongestCommonSubsequence' )
1033- expect (self .page .locator ('#results .summary strong' )).to_contain_text ('size-bound candidate' , timeout = 3000 )
1034- expect (self .page .locator ('.path' ).first .locator ('.size' )).to_have_text ('?' , timeout = 500 )
1050+ expect (self .page .locator ('#results .summary strong' )).to_have_text ('1 size-bound candidate' )
1051+ expect (self .page .locator ('.size.pending' )).to_have_count (0 )
1052+ expect (self .page .locator ('.path .size' )).to_have_text ('?' )
1053+ expect (self .page .locator ('.path .size' )).to_have_attribute ('title' , 'Size unavailable for one or more parameters' )
1054+ summaries = self .page .locator ('.growth' ).evaluate ('''dl => Object.fromEntries(
1055+ [...dl.querySelectorAll('dt')].map(term=>[term.textContent,term.nextElementSibling.textContent]))''' )
1056+ self .assertEqual (summaries , {'vars' : 'O(vars³)' , 'quadratic terms' : 'unavailable' })
1057+ expect (self .page .locator ('.steps .rule-link .oh' )).to_have_text ('?' )
1058+ edge = self .page .locator ('.scene-edge[data-edge="Satisfiability→QUBO"]' )
1059+ expect (edge ).to_have_count (1 )
1060+ self .assertTrue ({'route' , 'e-unknown' } <= set (edge .get_attribute ('class' ).split ()))
10351061
10361062 def test_directions_preloads_engine_before_graph_initialization (self ):
10371063 self .page .goto (self .base + 'graph.html#directions' )
0 commit comments