| | |
| | | --round01-debug-overlay-width="$OVERLAY_WIDTH" |
| | | --round01-disable-screenshot-refresh |
| | | --round01-debug-window-activation |
| | | --round01-waterfall-view-mode=vertical |
| | | --round01-debug-mouse-sequence="$sequence" |
| | | --round01-quick-switch-report="$report" |
| | | ) |
| | |
| | | PY |
| | | } |
| | | |
| | | assert_space_click_report() { |
| | | assert_space_click_filter_report() { |
| | | /usr/bin/python3 - "$1" <<'PY' |
| | | import json |
| | | import sys |
| | |
| | | root = report.get("rootView", {}) |
| | | columns = sorted(root.get("waterfallColumns", []), key=lambda column: column.get("appGroupIndex", 0)) |
| | | target_space_id = 1 |
| | | first_space_card = None |
| | | for column in columns: |
| | | cards = sorted(column.get("cards", []), key=lambda card: card.get("windowIndex", 0)) |
| | | first_space_card = next((card for card in cards if card.get("primarySpaceID") == target_space_id), None) |
| | | if first_space_card is not None: |
| | | break |
| | | |
| | | require(first_space_card is not None, "fixture must include at least one window in Space A1") |
| | | expected_window_id = first_space_card.get("windowID") |
| | | cards = [card for column in columns for card in column.get("cards", [])] |
| | | segments = root.get("spaceLaneSegments", []) |
| | | locked_segments = [segment for segment in segments if "locked" in segment.get("visualStates", [])] |
| | | |
| | | require(report.get("snapshotLoaded") is True, "snapshotLoaded must be true") |
| | | require(report.get("quickSwitchVisible") is False, "click-space must close Quick Switch after committing a window in that Space") |
| | | require(report.get("quickSwitchVisible") is True, "click-space must keep Quick Switch visible after locking Space filter") |
| | | require(report.get("spaceFilterActive") is True, "click-space must enable session Space filter") |
| | | require(report.get("spaceFilterLockedSpaceID") == target_space_id, "click-space must lock the clicked Space") |
| | | require(report.get("lastSpaceFilterAction") == "lock", "click-space must record a lock action") |
| | | require(root.get("spaceFilterActive") is True, "root report must expose active Space filter") |
| | | require(root.get("spaceFilterLockedSpaceID") == target_space_id, "root report must expose the locked Space") |
| | | require(root.get("lastSpaceLaneClickSpaceID") == target_space_id, "click-space must record the clicked Space") |
| | | require(root.get("spaceLaneFocusedSpaceID") is None, "click-space must not reuse persistent focus as its behavior") |
| | | require(root.get("lastCommittedWindowID") == expected_window_id, "click-space must commit the first window in the clicked Space") |
| | | require(report.get("lastCommittedWindowID") == expected_window_id, "session must surface the Space click commit") |
| | | require(report.get("lastActivationWindowID") == expected_window_id, "activation window must match the first window in clicked Space") |
| | | require(report.get("lastActivationResult") == "activated", "debug activation must activate the clicked Space window") |
| | | require(report.get("lastCommitSource") == "mouse", "click-space commit source must be mouse") |
| | | require(root.get("spaceLaneFocusedSpaceID") is None, "click-space must not reuse persistent hover focus as its behavior") |
| | | require(report.get("lastCommittedWindowID") is None, "ordinary click-space must not commit a window") |
| | | require(report.get("lastActivationWindowID") is None, "ordinary click-space must not activate a window") |
| | | require(report.get("lastActivationResult") is None, "ordinary click-space must not report activation") |
| | | require(report.get("lastCommitSource") is None, "ordinary click-space must not report a commit source") |
| | | require(cards, "fixture must include filtered cards for Space A1") |
| | | require(all(card.get("primarySpaceID") == target_space_id for card in cards), "click-space filter must only keep windows in clicked Space") |
| | | require(len(locked_segments) == 1, "exactly one Space Lane segment must expose locked") |
| | | require(locked_segments[0].get("spaceID") == target_space_id, "locked segment must be the clicked Space") |
| | | |
| | | print(json.dumps({ |
| | | "clickedSpaceID": root.get("lastSpaceLaneClickSpaceID"), |
| | | "lastCommittedWindowID": root.get("lastCommittedWindowID"), |
| | | "lastActivationResult": report.get("lastActivationResult") |
| | | "lockedSpaceID": root.get("spaceFilterLockedSpaceID"), |
| | | "visibleCardSpaceIDs": sorted({card.get("primarySpaceID") for card in cards}), |
| | | "quickSwitchVisible": report.get("quickSwitchVisible") |
| | | }, indent=2, ensure_ascii=False)) |
| | | PY |
| | | } |
| | |
| | | and inner.get("y", 0) + inner.get("height", 0) <= outer.get("y", 0) + outer.get("height", 0) + tolerance |
| | | ) |
| | | |
| | | def is_light_blue(color): |
| | | return ( |
| | | color.get("alpha", 0) >= 0.98 |
| | | and color.get("blue", 0) >= 0.98 |
| | | and color.get("green", 0) >= 0.90 |
| | | and color.get("red", 0) >= 0.80 |
| | | and color.get("blue", 0) > color.get("red", 0) + 0.04 |
| | | ) |
| | | |
| | | def is_white(color): |
| | | return ( |
| | | color.get("alpha", 0) >= 0.98 |
| | | and color.get("red", 0) >= 0.98 |
| | | and color.get("green", 0) >= 0.98 |
| | | and color.get("blue", 0) >= 0.98 |
| | | ) |
| | | |
| | | root = report.get("rootView", {}) |
| | | groups = root.get("spaceLaneDisplayGroups", []) |
| | | segments = root.get("spaceLaneSegments", []) |
| | |
| | | require(focused[0].get("label") == "B1", "hovered multi-display Space must be B1") |
| | | require("focused" in focused[0].get("visualStates", []), "focused B1 segment must expose focused visual state") |
| | | |
| | | idle_empty_segments = [ |
| | | empty_segments = [ |
| | | segment for segment in segments |
| | | if segment.get("windowCount") == 0 |
| | | ] |
| | | require(empty_segments, "multi-display visual fixture must include at least one empty Space") |
| | | require( |
| | | {"A3", "B1"}.issubset({segment.get("label") for segment in empty_segments}), |
| | | "multi-display visual fixture must include the A3/B1 empty Space regression pair" |
| | | ) |
| | | require( |
| | | all(segment.get("backgroundKind") == "clear" for segment in empty_segments), |
| | | "empty Spaces must not keep a dirty gray fill, even when focused/current/associated" |
| | | ) |
| | | require( |
| | | all(not segment.get("gradientColors", []) for segment in empty_segments), |
| | | "empty Spaces must clear stale gradient colors" |
| | | ) |
| | | require( |
| | | all(segment.get("backgroundColor", {}).get("alpha", 1) <= 0.01 for segment in empty_segments), |
| | | "empty Spaces must keep transparent fill" |
| | | ) |
| | | require( |
| | | all(segment.get("shadowOpacity", 1) <= 0.01 for segment in empty_segments), |
| | | "empty Spaces must not draw a shadow that reads as an interior gray fill" |
| | | ) |
| | | idle_occupied_segments = [ |
| | | segment for segment in segments |
| | | if segment.get("windowCount", 0) > 0 |
| | | and segment.get("isFocused") is not True |
| | | and segment.get("isCurrent") is not True |
| | | and segment.get("isAppAssociated") is not True |
| | | and segment.get("isWindowAssociated") is not True |
| | | ] |
| | | require(idle_empty_segments, "multi-display visual fixture must include at least one idle empty Space") |
| | | require( |
| | | all(segment.get("backgroundColor", {}).get("alpha", 1) <= 0.01 for segment in idle_empty_segments), |
| | | "idle empty Spaces must not keep a dirty gray fill" |
| | | ) |
| | | require(idle_occupied_segments, "multi-display visual fixture must include an idle occupied Space") |
| | | for segment in idle_occupied_segments: |
| | | gradient_colors = segment.get("gradientColors", []) |
| | | require(segment.get("backgroundKind") == "gradient", "idle occupied Spaces must use blue-white gradient fill") |
| | | require(len(gradient_colors) == 2, "idle occupied Space gradient must expose two color stops") |
| | | require(is_light_blue(gradient_colors[0]), "idle occupied Space gradient must start with pure light blue") |
| | | require(is_white(gradient_colors[1]), "idle occupied Space gradient must end with pure white") |
| | | fullscreen_segments = [segment for segment in segments if segment.get("type") == "fullscreen"] |
| | | require(fullscreen_segments, "multi-display visual fixture must include a fullscreen Space") |
| | | for segment in fullscreen_segments: |
| | | marker_frame = segment.get("fullscreenMarkerFrame", {}) |
| | | require(marker_frame.get("y") == 30, "fullscreen Space marker must keep the previous vertical style") |
| | | app_frame = segment.get("appFrame", {}) |
| | | marker_center_ratio = segment.get("fullscreenMarkerCenterRatio", 0) |
| | | marker_mid_y = marker_frame.get("y", 0) + marker_frame.get("height", 0) / 2 |
| | | app_mid_y = app_frame.get("y", 0) + app_frame.get("height", 0) / 2 |
| | | require(0.36 <= marker_center_ratio <= 0.44, "fullscreen Space marker must use adaptive vertical centering") |
| | | require(abs(marker_mid_y - app_mid_y) <= 2, "fullscreen App label must remain centered in the marker") |
| | | |
| | | print(json.dumps({ |
| | | "displayGroups": [ |
| | |
| | | run_report "$CLEAR_REPORT" "hover-space:1,hover-card:0:0" "hover-card:0:0" |
| | | assert_space_focus_clear_report "$CLEAR_REPORT" |
| | | |
| | | run_report "$SPACE_CLICK_REPORT" "click-space:1" "click-space:1" "$FIXTURE_APP_COUNT" "$FIXTURE_WINDOWS_PER_APP" hidden |
| | | assert_space_click_report "$SPACE_CLICK_REPORT" |
| | | run_report "$SPACE_CLICK_REPORT" "click-space:1" "click-space:1" "$FIXTURE_APP_COUNT" "$FIXTURE_WINDOWS_PER_APP" visible |
| | | assert_space_click_filter_report "$SPACE_CLICK_REPORT" |
| | | |
| | | run_report "$REMOTE_REPORT" "hover-space:1,click-app:$REMOTE_APP_INDEX" "click-app:$REMOTE_APP_INDEX" "$FIXTURE_APP_COUNT" "$FIXTURE_WINDOWS_PER_APP" hidden |
| | | assert_remote_click_report "$REMOTE_REPORT" |