From 3099bfc571cfc6a48179252e30a3111ed09caffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Thu, 11 Jan 2024 19:01:46 +0100 Subject: [PATCH] tests: Add fittsy test Both the dash and top bar items are expected to extend to the screen edge, to make them easier click targets according to Fitts' law. This has the tendency to break fairly regularly, so add a small test that checks the Fittsiness of the show-apps and activities buttons to catch regressions. Related: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7318 Part-of: --- tests/meson.build | 3 ++ tests/shell/fittsy.js | 122 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 tests/shell/fittsy.js diff --git a/tests/meson.build b/tests/meson.build index a22a0d949..821c83cd9 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -48,6 +48,9 @@ shell_tests = [ 'name': 'headlessStart', 'options': ['--hotplug'], }, + { + 'name': 'fittsy', + }, ] gvc_typelib_path = fs.parent(libgvc.get_variable('libgvc_gir')[1].full_path()) diff --git a/tests/shell/fittsy.js b/tests/shell/fittsy.js new file mode 100644 index 000000000..53f58e0e4 --- /dev/null +++ b/tests/shell/fittsy.js @@ -0,0 +1,122 @@ +/* eslint camelcase: ["error", { properties: "never", allow: ["^script_"] }] */ + +import Clutter from 'gi://Clutter'; +import Shell from 'gi://Shell'; + +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import {sleep} from 'resource:///org/gnome/shell/ui/scripting.js'; + +const {Orientation, PickMode, TextDirection} = Clutter; +const EPSILON = 0.1; + +function defineScriptEvent(eventName, description) { + Shell.PerfLog.get_default().define_event( + `script.${eventName}`, description, 'i'); +} + +function scriptEvent(eventName, bool) { + Shell.PerfLog.get_default().event_i(`script.${eventName}`, + Number(bool)); +} + +function checkFittsiness(eventName, actor, orientation, edge) { + const [x, y] = actor.get_transformed_position(); + const pickCoords = orientation === Orientation.HORIZONTAL + ? [edge, y + Math.floor(actor.height / 2)] + : [x + Math.floor(actor.width / 2), edge]; + const pickedActor = global.stage.get_actor_at_pos( + PickMode.REACTIVE, ...pickCoords); + + scriptEvent(eventName, pickedActor === actor); +} + +/** + * run: + */ +export async function run() { + defineScriptEvent('fittsyDash', 'Dash extends to screen edge'); + defineScriptEvent('fittsyTopBarVert', 'Top bar extends to top screen edge'); + defineScriptEvent('fittsyTopBarHorzLTR', 'Top bar extends to left screen edge'); + defineScriptEvent('fittsyTopBarHorzRTL', 'Top bar extends to right screen edge'); + + const {primaryMonitor} = Main.layoutManager; + const topEdge = primaryMonitor.y + EPSILON; + const bottomEdge = primaryMonitor.y + primaryMonitor.height - EPSILON; + const leftEdge = primaryMonitor.x + EPSILON; + const rightEdge = primaryMonitor.x + primaryMonitor.width - EPSILON; + + const showApps = Main.overview.dash.showAppsButton; + console.debug('Checking that dash extends to bottom screen edge'); + checkFittsiness('fittsyDash', + showApps, Orientation.VERTICAL, bottomEdge); + + const activitiesButton = Main.panel.statusArea.activities; + console.debug('Checking that top bar extends to top screen edge'); + checkFittsiness('fittsyTopBarVert', + activitiesButton, Orientation.VERTICAL, topEdge); + + Main.panel.text_direction = TextDirection.LTR; + await sleep(50); + + console.debug('Checking that top bar extends to left screen edge for LTR'); + checkFittsiness('fittsyTopBarHorzLTR', + activitiesButton, Orientation.HORIZONTAL, leftEdge); + + Main.panel.text_direction = TextDirection.RTL; + await sleep(50); + + console.debug('Checking that top bar extends to right screen edge for RTL'); + checkFittsiness('fittsyTopBarHorzRTL', + activitiesButton, Orientation.HORIZONTAL, rightEdge); +} + +let fittsyDash = false; +let fittsyTopBarVert = false; +let fittsyTopBarHorzLTR = false; +let fittsyTopBarHorzRTL = false; + +/** + * @param {number} time + * @param {number} num + */ +export function script_fittsyDash(time, num) { + fittsyDash = num !== 0; +} + +/** + * @param {number} time + * @param {number} num + */ +export function script_fittsyTopBarVert(time, num) { + fittsyTopBarVert = num !== 0; +} + +/** + * @param {number} time + * @param {number} num + */ +export function script_fittsyTopBarHorzLTR(time, num) { + fittsyTopBarHorzLTR = num !== 0; +} + +/** + * @param {number} time + * @param {number} num + */ +export function script_fittsyTopBarHorzRTL(time, num) { + fittsyTopBarHorzRTL = num !== 0; +} + +export function finish() { + if (!fittsyDash) + throw new Error('Dash does not extend to screen edge'); + + if (!fittsyTopBarVert) + throw new Error('Top bar does not extend to top screen edge'); + + if (!fittsyTopBarHorzLTR) + throw new Error('Top bar does not extend to left screen edge'); + + if (!fittsyTopBarHorzRTL) + throw new Error('Top bar does not extend to right screen edge'); +}