@@ -184,4 +184,96 @@ test.describe("ULabel Basic Functionality", () => {
184184 const margin_near_top = await page . locator ( conf_id ) . evaluate ( ( el ) => el . style . marginTop ) ;
185185 expect ( margin_near_top ) . toBe ( "-1em" ) ;
186186 } ) ;
187+
188+ test ( "confidence card flip check accounts for annbox scroll position" , async ( { page } ) => {
189+ await wait_for_ulabel_init ( page ) ;
190+
191+ const subtask_key = await page . evaluate ( ( ) => window . ulabel . get_current_subtask_key ( ) ) ;
192+ const conf_id = `#global_annotation_confidence__${ subtask_key } ` ;
193+
194+ // Middle-image annotation displays with card above (no flip)
195+ await draw_bbox ( page , [ 400 , 400 ] , [ 500 , 500 ] ) ;
196+ await page . waitForTimeout ( 100 ) ;
197+ await page . mouse . move ( 450 , 450 ) ;
198+ await page . waitForTimeout ( 200 ) ;
199+
200+ const margin_unscrolled = await page . locator ( conf_id ) . evaluate ( ( el ) => el . style . marginTop ) ;
201+ expect ( margin_unscrolled ) . toBe ( "-9.5em" ) ;
202+
203+ // Scroll the annbox down so the annotation's visible top approaches viewport top,
204+ // then re-trigger the position calculation (simulating a re-hover after scroll).
205+ await page . evaluate ( ( ) => {
206+ const u = window . ulabel ;
207+ const annbox = document . getElementById ( u . config . annbox_id ) ;
208+ annbox . scrollTop = 500 ;
209+ const annid = u . get_current_subtask ( ) . annotations . ordering [ 0 ] ;
210+ u . get_current_subtask ( ) . state . edit_candidate = { annid : annid } ;
211+ u . show_global_edit_suggestion ( annid ) ;
212+ } ) ;
213+ await page . waitForTimeout ( 100 ) ;
214+
215+ const margin_scrolled = await page . locator ( conf_id ) . evaluate ( ( el ) => el . style . marginTop ) ;
216+ expect ( margin_scrolled ) . toBe ( "-1em" ) ;
217+ } ) ;
218+
219+ test ( "confidence card picks a class name even when all confidences are 0" , async ( { page } ) => {
220+ await wait_for_ulabel_init ( page ) ;
221+
222+ // Directly install an annotation with zero confidence and trigger the confidence dialog.
223+ // annotation.ts pads missing classes with confidence: 0.0, so this represents a common
224+ // "no class info supplied" import case where earlier code showed "Unknown".
225+ await page . evaluate ( async ( ) => {
226+ const u = window . ulabel ;
227+ const anno = {
228+ id : "test_zero" ,
229+ spatial_type : "bbox" ,
230+ spatial_payload : [ [ 150 , 150 ] , [ 250 , 250 ] ] ,
231+ classification_payloads : [ { class_id : 10 , confidence : 0 } ] ,
232+ } ;
233+ await u . set_annotations ( [ anno ] , "car_detection" ) ;
234+ } ) ;
235+ await page . waitForTimeout ( 100 ) ;
236+
237+ await page . mouse . move ( 200 , 200 ) ;
238+ await page . waitForTimeout ( 200 ) ;
239+
240+ const subtask_key = await page . evaluate ( ( ) => window . ulabel . get_current_subtask_key ( ) ) ;
241+ const conf_id = `#global_annotation_confidence__${ subtask_key } ` ;
242+ const classname = ( await page . locator ( `${ conf_id } .annotation-confidence-classname` ) . textContent ( ) ) . trim ( ) ;
243+ const value = ( await page . locator ( `${ conf_id } .annotation-confidence-value` ) . textContent ( ) ) . trim ( ) ;
244+
245+ expect ( classname ) . toBe ( "Sedan" ) ;
246+ expect ( value ) . toBe ( "Confidence: 0.00" ) ;
247+ } ) ;
248+
249+ test ( "switching subtasks clears hovered_annid on the outgoing subtask" , async ( { page } ) => {
250+ await wait_for_ulabel_init ( page ) ;
251+
252+ await draw_bbox ( page , [ 200 , 200 ] , [ 300 , 300 ] ) ;
253+ await page . waitForTimeout ( 100 ) ;
254+
255+ // Hover to set hovered_annid on the current subtask
256+ await page . mouse . move ( 250 , 250 ) ;
257+ await page . waitForTimeout ( 200 ) ;
258+
259+ const before = await page . evaluate ( ( ) => {
260+ const u = window . ulabel ;
261+ const key = u . get_current_subtask_key ( ) ;
262+ return {
263+ key : key ,
264+ hovered_annid : u . subtasks [ key ] . state . hovered_annid ,
265+ } ;
266+ } ) ;
267+ expect ( before . hovered_annid ) . not . toBeNull ( ) ;
268+
269+ // Switch to the next subtask
270+ await page . evaluate ( ( ) => window . ulabel . switch_to_next_subtask ( ) ) ;
271+ await page . waitForTimeout ( 100 ) ;
272+
273+ // The previous subtask's hovered_annid must be cleared so its stale outline doesn't linger
274+ const after = await page . evaluate ( ( old_key ) => {
275+ return window . ulabel . subtasks [ old_key ] . state . hovered_annid ;
276+ } , before . key ) ;
277+ expect ( after ) . toBeNull ( ) ;
278+ } ) ;
187279} ) ;
0 commit comments