Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions linux/changelog.d/3931.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
A window showing a connection had no way to add a new connection.
53 changes: 52 additions & 1 deletion linux/crates/app/src/ui/workspace/tests/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use libadwaita::prelude::*;
use super::{served_table, shell_of};
use crate::test_support::{descendants, wait_until};
use crate::ui::SessionWindowInput;
use crate::ui::session_window::tests::{Script, TestWindow};
use crate::ui::session_window::tests::{Script, TestWindow, WAIT};
use crate::ui::workspace::{WorkspaceShell, WorkspaceTab};

fn overview_new_tab_button(overview: &adw::TabOverview) -> gtk::Button {
Expand Down Expand Up @@ -418,3 +418,54 @@ fn the_overview_opens_a_tab_in_a_session_that_came_forward_from_its_own_input()
"the new tab went to a session behind"
);
}

/// Choose New Connection… in the main menu under `header`, as a click
/// does, and wait for the connection dialog.
fn choose_new_connection(test: &TestWindow, header: &impl IsA<gtk::Widget>) {
let button = descendants(header)
.into_iter()
.filter_map(|widget| widget.downcast::<gtk::MenuButton>().ok())
.find(gtk::MenuButton::is_primary)
.expect("the main menu button");
button.popup();
let menu = button.popover().expect("the main menu");
wait_until(WAIT, || menu.is_visible()).expect("the main menu to open");
// GTK keeps a menu item private and gives it no action name.
let item = descendants(&menu)
.into_iter()
.find(|widget| {
widget.type_().name() == "GtkModelButton"
&& widget.property::<Option<String>>("text").as_deref() == Some("New Connection…")
})
.expect("New Connection… in the main menu");
wait_until(WAIT, || item.is_sensitive()).expect("New Connection… to be enabled");

item.emit_by_name::<()>("clicked", &[]);

wait_until(WAIT, || test.window.visible_dialog().is_some()).expect("the connection dialog");
}

#[gtk4::test]
fn the_main_menu_adds_a_connection_beside_an_open_one() {
let test = TestWindow::connected("MainMenuNewConnection");
// The overview's own menu button is a primary one too.
let header = shell_of(&test.workspace()).imp().sidebar_header.get();
choose_new_connection(&test, &header);
}

#[gtk4::test]
fn the_main_menu_adds_a_connection_with_none_open() {
let test = TestWindow::picker("PickerMenuNewConnection");
let menu = test.app.menu_by_id("primary_menu").expect("the primary menu");
let first = menu.item_link(0, "section").expect("a first section");
assert_eq!(
first
.item_attribute_value(0, "action", None)
.and_then(|value| value.get::<String>())
.as_deref(),
Some("win.new-connection"),
"New Connection… does not lead the menu"
);

choose_new_connection(&test, &test.window.content().expect("the picker"));
}
4 changes: 4 additions & 0 deletions linux/data/resources/gtk/menus.ui
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
startup; the windows read the menus with menu_by_id. -->
<menu id="primary_menu">
<section>
<item>
<attribute name="label" translatable="yes">New Connection…</attribute>
<attribute name="action">win.new-connection</attribute>
</item>
<item>
<attribute name="label" translatable="yes">New Window</attribute>
<attribute name="action">app.new-window</attribute>
Expand Down
Loading