diff --git a/ChangeLog b/ChangeLog index 3fca7ea7..06ec394d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,9 @@ ## Interface and handling +- keep real-browser regression inputs stable when maintainers replace the GUI + examples, while continuing to verify that each task's example loads + - --outNumberPerSeed selects each seed's best candidate sites before final deduplication, energy/overlap/count filtering; model P ranks left-most-anchor ensembles; zero preserves ordinary prediction; the GUI exposes the quota next @@ -326,6 +329,11 @@ energies, restricted partition sums, and trackers. + Independent chain-enumeration, traceback, seed-only, mode-matrix, merge, filter, CLI and unchanged-probability regressions; register/install sources. +261026 Alexander Mitrofanov + * scripts/wasm/test-browser.py + * decouple deterministic numerical browser checks from replaceable GUI example + payloads while retaining real-browser coverage of prediction/evaluation loading + 261026 Alexander Mitrofanov * gui/app.js, gui/{index.html,styles.css}, scripts/wasm/test-browser.py * place Explicit seeds beside a half-width Seed constraint selector and halve diff --git a/scripts/wasm/test-browser.py b/scripts/wasm/test-browser.py index cc62414a..8457c058 100644 --- a/scripts/wasm/test-browser.py +++ b/scripts/wasm/test-browser.py @@ -41,9 +41,23 @@ def open_group(key): expect(page.locator('#tab-' + key)).to_have_attribute('aria-selected', 'true') assert page.locator('.parameter-group:visible').count() == 1 - def load_example(task='prediction'): + def load_reference(task='prediction'): page.locator('#examples-menu summary').click() - page.get_by_role('button', name='Evaluate a duplex' if task == 'evaluation' else 'Short duplex', exact=False).click() + page.locator(f'#example-options [data-example-task="{task}"]').click() + expect(page.locator('#query')).not_to_have_value('') + expect(page.locator('#target')).not_to_have_value('') + if task == 'evaluation': + expect(page.locator('#rri')).not_to_have_value('') + + # Examples are maintainer-editable content. Exercise their loading, then + # use a fixed small pair so numerical browser regressions stay stable. + page.locator('#reset').click() + if task == 'evaluation': + page.get_by_role('radio', name='Evaluation').check() + page.locator('#query').fill('>query\nGGGAGGAGGG\n') + page.locator('#target').fill('>target\nCCCUCCUCCC\n') + if task == 'evaluation': + page.locator('#rri').fill('1||||||||||&1||||||||||') expect(page.locator('#query')).to_have_value('>query\nGGGAGGAGGG\n') def download_archive(session=None): @@ -90,11 +104,13 @@ def predict(): page.keyboard.press('ArrowLeft') expect(page.get_by_role('radio', name='Prediction')).to_be_checked() page.locator('#examples-menu summary').click() - expect(page.get_by_role('button', name='Short duplex', exact=False)).to_be_visible() - expect(page.get_by_role('button', name='Evaluate a duplex', exact=False)).not_to_be_visible() + prediction_example = page.locator('#example-options [data-example-task="prediction"]') + evaluation_example = page.locator('#example-options [data-example-task="evaluation"]') + expect(prediction_example).to_be_visible() + expect(evaluation_example).not_to_be_visible() page.get_by_role('radio', name='Evaluation').check() - expect(page.get_by_role('button', name='Evaluate a duplex', exact=False)).to_be_visible() - expect(page.get_by_role('button', name='Short duplex', exact=False)).not_to_be_visible() + expect(evaluation_example).to_be_visible() + expect(prediction_example).not_to_be_visible() page.get_by_role('radio', name='Prediction').check() page.locator('#examples-menu summary').click() @@ -242,7 +258,7 @@ def predict(): compute.click() expect(page.locator('#input-error')).to_contain_text('use only') expect(page.locator('#loading')).not_to_be_visible() - load_example() + load_reference() fill('temperature', '101') open_group('sequence-input') compute.click() @@ -251,7 +267,7 @@ def predict(): expect(page.locator('#query')).to_have_value('') expect(page.locator('#target')).to_have_value('') expect(page.locator('#rri')).to_have_value('') - load_example() + load_reference() # Disabled stale edits neither block a run nor leak into JSON. Re-enabling # restores local edits; loading/storing uses effective native settings. @@ -287,7 +303,7 @@ def predict(): page.locator('#qAcc').select_option('C') expect(page.locator('#qShape')).to_have_value('invalid inactive shape') page.locator('#reset').click() - load_example() + load_reference() # Reference prediction, selectable CSV output and independent table visibility. fill('outNumber', 10) @@ -378,7 +394,7 @@ def predict(): page.set_viewport_size({'width': 1440, 'height': 1100}) # Multi-FASTA prediction, signed inclusive output and additional files. - load_example() + load_reference() fill('outNumber', 1) fill('query', '>q1\nGGGAGGAGGG\n>q2\nGGGAGGAGGG') fill('qIdxPos0', -3) @@ -435,7 +451,7 @@ def predict(): fill('rri', '1||||||||||&1||||||||||') compute.click() expect(page.locator('#input-error')).to_contain_text('exactly one') - load_example('evaluation') + load_reference('evaluation') fill('rri', '1||||||||||&1||||||||||:1|||||||||&2|||||||||') open_group('output-options') page.locator('#output-options input[value="detailed"]').check() @@ -475,7 +491,7 @@ def predict(): # Startup and synchronous C++ cancellation both allow a fresh prediction. page.get_by_role('radio', name='Prediction').check() - load_example() + load_reference() held_routes = [] session_count = sessions.count() page.route('**/wasm/intarna.wasm', lambda route: held_routes.append(route)) @@ -494,7 +510,7 @@ def predict(): page.keyboard.press('Escape') expect(status).to_contain_text('aborted') expect(sessions).to_have_count(session_count) - load_example() + load_reference() predict() fill('query', '>no_pairs\nNNNNNNNNNN') @@ -508,7 +524,7 @@ def predict(): assert active.locator('tbody img').count() == 0 assert '