# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/.
import multiprocessing import re
import mozunit import pytest from tryselect.push import LARGE_PUSH_THRESHOLD from tryselect.selectors.chooser import (
ChooserConfig,
resolve_artifact_state,
resolve_large_push_context,
) from tryselect.selectors.chooser.app import create_application
for expected in expected_output: assert expected in response.data
# Guard against debug leftovers creeping back into the checkbox onchange. assert b"console.log"notin response.data
def test_try_chooser_cross_section_narrowing_preconditions(app): # filter.js's cross-section narrowing pools checkbox filter values per # attribute and scopes them by that attribute's "namespace" — the set # of values any section renders as a checkbox option. For selecting # a Platform row to narrow Test rows, two structural facts must hold: # 1. Platform's checkbox values carry build_platform (contributing # to the build_platform namespace). # 2. The tasks object serialized into the page carries build_platform # on test tasks too, so the namespace has something to match. # If either breaks, selecting a platform silently stops constraining # tests, which is precisely the regression this guards against.
client = app.test_client()
response = client.get("/") assert response.status_code == 200
# A Platform checkbox must exist carrying build_platform=[windows]. # Use lookaheads so attribute ordering on the <input> tag isn't part # of the contract — an unrelated template shuffle shouldn't look # like a cross-section narrowing regression. assert re.search(
rb"<input\b(?=[^>]*\bname=\"build\")"
rb"(?=[^>]*\bvalue='\{\"build_platform\": \[\"windows\"\]\}')",
response.data,
) # Test and mochitest task entries in the tasks global must include # build_platform so JS can narrow them by platform. Match on attribute # presence, not on JSON key order, so an unrelated attribute addition # can't masquerade as a regression. assert re.search(
rb'"test-windows-xpcshell-e10s":\s*\{[^}]*"build_platform":\s*"windows"',
response.data,
) assert re.search(
rb'"test-windows-mochitest-e10s":\s*\{[^}]*"build_platform":\s*"windows"',
response.data,
)
def test_try_chooser_buildtype_radio_is_scalar(app): # filter.js apply() compares task.build_type !== buildTypeFilter as # strings. The radio values must stay scalar JSON; moving them to # arrays (like section checkbox values) would silently break the # comparison without a corresponding filter.js change.
client = app.test_client()
response = client.get("/") assert response.status_code == 200 assert b"""value='{"build_type": "opt"}'"""in response.data assert b"""value='{"build_type": "debug"}'"""in response.data
# Exclude-filter input should be present and wired to the debounced # handler so keystrokes don't trigger a full re-render each time. Scope # the handler assertion to the exclude-filter element itself; chunk # inputs share scheduleApplyFilters and would otherwise satisfy a bare # substring match. assert re.search(
rb'<input[^>]*\bid="exclude-filter"[^>]*\boninput="scheduleApplyFilters\(\);"',
response.data,
) assert b'placeholder="Exclude jobs containing'in response.data assert b'aria-label="Exclude jobs containing"'in response.data # Don't persist filter text across sessions via browser autofill. assert b'autocomplete="off"'in response.data # Exclude-filter must sit outside the form so Enter can't submit it. assert response.data.index(b'id="exclude-filter"') < response.data.index(
b'<form id="submit-tasks"'
)
# Selection list + hidden form field that carries the chosen labels. assert b'<ul id="selection">'in response.data assert b'id="selected-tasks"'in response.data assert b'name="selected-tasks"'in response.data
# Large-push warning is rendered hidden and references the actual threshold # that push.py uses to trigger the deprioritization prompt. assert b'id="large-push-warning"'in response.data # Polite live region so count updates don't spam assertive announcements. assert b'role="status"'in response.data assert b'aria-live="polite"'in response.data assert b'id="large-push-count"'in response.data assert f"over {LARGE_PUSH_THRESHOLD} tasks".encode() in response.data assert b"narrowing your selection"in response.data # Defaults match push.py when no rebuild/priority is set. assert b"const largePushMultiplier = 1;"in response.data assert b"const largePushSuppressed = false;"in response.data
def test_try_chooser_cancel(app, queue: multiprocessing.Queue):
client = app.test_client()
response = client.post("/", data={"action": "Cancel"}) assert response.status_code == 200 assert b"You may now close this page"in response.data assert queue.get() == {"tasks": [], "use_artifact": False}
def test_try_chooser_push_empty(app, queue: multiprocessing.Queue):
client = app.test_client()
response = client.post("/", data={"action": "Push", "selected-tasks": ""}) assert response.status_code == 200 assert b"You may now close this page"in response.data assert queue.get() == {"tasks": [], "use_artifact": False}
def test_try_chooser_push_selected_tasks(app, queue: multiprocessing.Queue):
client = app.test_client()
response = client.post( "/",
data={ "action": "Push", "selected-tasks": "build-windows\ntest-windows-mochitest-e10s",
},
) assert response.status_code == 200 assert b"You may now close this page"in response.data
result = queue.get() assert set(result["tasks"]) == {"build-windows", "test-windows-mochitest-e10s"} assert result["use_artifact"] isFalse
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.