mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-25 18:55:27 -06:00
Trying to size the window based on VM desktop resolution does not do the correct thing when host fractional scaling is enabled and using spice. The best we can do here is ask the viewer widget for its preferred size Signed-off-by: Cole Robinson <crobinso@redhat.com>
616 lines
20 KiB
Python
616 lines
20 KiB
Python
# This work is licensed under the GNU GPLv2 or later.
|
|
# See the COPYING file in the top-level directory.
|
|
|
|
import os
|
|
import tempfile
|
|
|
|
import libvirt
|
|
import pytest
|
|
|
|
import virtinst
|
|
from virtinst import log
|
|
|
|
import tests
|
|
from . import lib
|
|
|
|
|
|
def _vm_wrapper(vmname, uri="qemu:///system", opts=None):
|
|
"""
|
|
Decorator to define+start a VM and clean it up on exit
|
|
"""
|
|
def wrap1(fn):
|
|
def wrapper(app, *args, **kwargs):
|
|
app.error_if_already_running()
|
|
xmlfile = "%s/live/%s.xml" % (tests.utils.UITESTDATADIR, vmname)
|
|
conn = libvirt.open(uri)
|
|
dom = conn.defineXML(open(xmlfile).read())
|
|
try:
|
|
dom.create()
|
|
app.uri = uri
|
|
app.conn = conn
|
|
extra_opts = (opts or [])
|
|
extra_opts += ["--show-domain-console", vmname]
|
|
# Enable stats for more code coverage
|
|
keyfile = "statsonly.ini"
|
|
app.open(extra_opts=extra_opts, keyfile=keyfile)
|
|
fn(app, dom, *args, **kwargs)
|
|
finally:
|
|
try:
|
|
app.stop()
|
|
except Exception:
|
|
pass
|
|
try:
|
|
flags = 0
|
|
if "qemu" in uri:
|
|
flags = (libvirt.VIR_DOMAIN_UNDEFINE_NVRAM |
|
|
libvirt.VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA)
|
|
dom.undefineFlags(flags)
|
|
dom.destroy()
|
|
except Exception:
|
|
pass
|
|
return wrapper
|
|
return wrap1
|
|
|
|
|
|
def _create_qcow2_file(fn):
|
|
def wrapper(app, *args, **kwargs):
|
|
tmpdir = tempfile.TemporaryDirectory(prefix="uitests-tmp")
|
|
dname = tmpdir.name
|
|
try:
|
|
fname = os.path.join(dname, "test.img")
|
|
os.system("qemu-img create -f qcow2 %s 1M > /dev/null" % fname)
|
|
os.system("chmod 700 %s" % dname)
|
|
fn(fname, app, *args, **kwargs)
|
|
finally:
|
|
poolname = os.path.basename(dname)
|
|
try:
|
|
pool = app.conn.storagePoolLookupByName(poolname)
|
|
pool.destroy()
|
|
pool.undefine()
|
|
except Exception:
|
|
log.debug("Error cleaning up pool", exc_info=True)
|
|
return wrapper
|
|
|
|
|
|
def _destroy(app, win):
|
|
smenu = win.find("Menu", "toggle button")
|
|
smenu.click()
|
|
smenu.find("Force Off", "menu item").click()
|
|
app.click_alert_button("you sure", "Yes")
|
|
run = win.find("Run", "push button")
|
|
lib.utils.check(lambda: run.sensitive)
|
|
|
|
|
|
###############################################
|
|
# Test live console connections with stub VMs #
|
|
###############################################
|
|
|
|
def _checkConsoleStandard(app, dom):
|
|
"""
|
|
Shared logic for general console handling
|
|
"""
|
|
ignore = dom
|
|
win = app.topwin
|
|
con = win.find("console-gfx-viewport")
|
|
lib.utils.check(lambda: con.showing)
|
|
|
|
win.find("Virtual Machine", "menu").click()
|
|
win.find("Take Screenshot", "menu item").click()
|
|
chooser = app.root.find(None, "file chooser")
|
|
fname = chooser.find("Name", "text").text
|
|
app.rawinput.pressKey("Enter")
|
|
lib.utils.check(lambda: os.path.exists(fname))
|
|
os.unlink(fname)
|
|
lib.utils.check(lambda: win.active)
|
|
|
|
win.find("Send Key", "menu").click()
|
|
win.find(r"Ctrl\+Alt\+F1", "menu item").click()
|
|
win.find("Send Key", "menu").click()
|
|
win.find(r"Ctrl\+Alt\+F10", "menu item").click()
|
|
win.find("Send Key", "menu").click()
|
|
win.find(r"Ctrl\+Alt\+Delete", "menu item").click()
|
|
|
|
# 'Resize to VM' testing
|
|
oldsize = win.size
|
|
win.find("^View$", "menu").click()
|
|
win.find("Resize to VM", "menu item").click()
|
|
newsize = win.size
|
|
lib.utils.check(lambda: oldsize != newsize)
|
|
|
|
# Fullscreen testing
|
|
win.find("^View$", "menu").click()
|
|
win.find("Fullscreen", "check menu item").click()
|
|
fstb = win.find("Fullscreen Toolbar")
|
|
lib.utils.check(lambda: fstb.showing)
|
|
lib.utils.check(lambda: win.size != newsize)
|
|
|
|
# Wait for toolbar to hide, then reveal it again
|
|
lib.utils.check(lambda: not fstb.showing, timeout=5)
|
|
app.rawinput.point(win.position[0] + win.size[0] / 2, 0)
|
|
lib.utils.check(lambda: fstb.showing)
|
|
# Move it off and have it hide again
|
|
win.point()
|
|
lib.utils.check(lambda: not fstb.showing, timeout=5)
|
|
app.rawinput.point(win.position[0] + win.size[0] / 2, 0)
|
|
lib.utils.check(lambda: fstb.showing)
|
|
|
|
# Click stuff and exit fullscreen
|
|
win.find("Fullscreen Send Key").click()
|
|
app.rawinput.pressKey("Escape")
|
|
win.find("Fullscreen Exit").click()
|
|
lib.utils.check(lambda: win.size == newsize)
|
|
|
|
# Trigger pointer grab, verify title was updated
|
|
win.click()
|
|
lib.utils.check(lambda: "Control_L" in win.name)
|
|
# Ungrab
|
|
win.keyCombo("<ctrl><alt>")
|
|
lib.utils.check(lambda: "Control_L" not in win.name)
|
|
|
|
# Tweak scaling
|
|
win.window_maximize()
|
|
win.find("^View$", "menu").click()
|
|
scalemenu = win.find("Scale Display", "menu")
|
|
scalemenu.point()
|
|
scalemenu.find("Never", "radio menu item").click()
|
|
win.find("^View$", "menu").click()
|
|
scalemenu = win.find("Scale Display", "menu")
|
|
scalemenu.point()
|
|
scalemenu.find("Only", "radio menu item").click()
|
|
win.find("^View$", "menu").click()
|
|
scalemenu = win.find("Scale Display", "menu")
|
|
scalemenu.point()
|
|
scalemenu.find("Always", "radio menu item").click()
|
|
|
|
# 'Resize to VM' again, to hit the scaling->always case
|
|
oldsize = win.size
|
|
win.find("^View$", "menu").click()
|
|
win.find("Resize to VM", "menu item").click()
|
|
newsize = win.size
|
|
lib.utils.check(lambda: oldsize != newsize)
|
|
|
|
win.window_close()
|
|
|
|
|
|
@_vm_wrapper("uitests-vnc-standard")
|
|
def testConsoleVNCStandard(app, dom):
|
|
return _checkConsoleStandard(app, dom)
|
|
|
|
|
|
@_vm_wrapper("uitests-spice-standard")
|
|
def testConsoleSpiceStandard(app, dom):
|
|
return _checkConsoleStandard(app, dom)
|
|
|
|
|
|
def _checkConsoleFocus(app, dom):
|
|
"""
|
|
Shared logic for console keyboard grab handling
|
|
"""
|
|
win = app.topwin
|
|
con = win.find("console-gfx-viewport")
|
|
lib.utils.check(lambda: con.showing)
|
|
|
|
# Check that modifiers don't work when console grabs pointer
|
|
win.click()
|
|
app.sleep(.5) # make sure window code has time to adjust modifiers
|
|
win.keyCombo("<ctrl><shift>w")
|
|
lib.utils.check(lambda: win.showing)
|
|
dom.destroy()
|
|
win.find("Guest is not running.")
|
|
win.grab_focus()
|
|
app.sleep(.5) # make sure window code has time to adjust modifiers
|
|
win.keyCombo("<ctrl><shift>w")
|
|
lib.utils.check(lambda: not win.showing)
|
|
|
|
|
|
@_vm_wrapper("uitests-vnc-standard")
|
|
def testConsoleVNCFocus(app, dom):
|
|
return _checkConsoleFocus(app, dom)
|
|
|
|
|
|
@_vm_wrapper("uitests-spice-standard")
|
|
def testConsoleSpiceFocus(app, dom):
|
|
return _checkConsoleFocus(app, dom)
|
|
|
|
|
|
def _checkPassword(app):
|
|
"""
|
|
Shared logic for password handling
|
|
"""
|
|
win = app.topwin
|
|
con = win.find("console-gfx-viewport")
|
|
lib.utils.check(lambda: not con.showing)
|
|
passwd = win.find("Password:", "password text")
|
|
lib.utils.check(lambda: passwd.showing)
|
|
|
|
# Check wrong password handling
|
|
passwd.typeText("xx")
|
|
win.find("Login", "push button").click()
|
|
app.click_alert_button("Viewer authentication error", "OK")
|
|
savecheck = win.find("Save this password", "check box")
|
|
if not savecheck.checked:
|
|
savecheck.click()
|
|
passwd.typeText("yy")
|
|
app.rawinput.pressKey("Enter")
|
|
app.click_alert_button("Viewer authentication error", "OK")
|
|
|
|
# Check proper password
|
|
passwd.text = ""
|
|
passwd.typeText("goodp")
|
|
win.find("Login", "push button").click()
|
|
lib.utils.check(lambda: con.showing)
|
|
|
|
# Restart VM to retrigger console connect
|
|
_destroy(app, win)
|
|
win.find("Run", "push button").click()
|
|
lib.utils.check(lambda: passwd.showing)
|
|
# Password should be filled in
|
|
lib.utils.check(lambda: bool(passwd.text))
|
|
# Uncheck 'Save password' and login, which will delete it from keyring
|
|
savecheck.click()
|
|
win.find("Login", "push button").click()
|
|
lib.utils.check(lambda: con.showing)
|
|
|
|
# Restart VM to retrigger console connect
|
|
_destroy(app, win)
|
|
win.find("Run", "push button").click()
|
|
lib.utils.check(lambda: passwd.showing)
|
|
# Password should be empty now
|
|
lib.utils.check(lambda: not bool(passwd.text))
|
|
|
|
|
|
@_vm_wrapper("uitests-vnc-password")
|
|
def testConsoleVNCPassword(app, dom):
|
|
ignore = dom
|
|
return _checkPassword(app)
|
|
|
|
|
|
@_vm_wrapper("uitests-spice-password")
|
|
def testConsoleSpicePassword(app, dom):
|
|
ignore = dom
|
|
return _checkPassword(app)
|
|
|
|
|
|
@_vm_wrapper("uitests-vnc-password",
|
|
opts=["--test-options=fake-vnc-username"])
|
|
def testConsoleVNCPasswordUsername(app, dom):
|
|
ignore = dom
|
|
win = app.topwin
|
|
con = win.find("console-gfx-viewport")
|
|
lib.utils.check(lambda: not con.showing)
|
|
passwd = win.find("Password:", "password text")
|
|
lib.utils.check(lambda: passwd.showing)
|
|
username = win.find("Username:", "text")
|
|
lib.utils.check(lambda: username.showing)
|
|
|
|
# Since we are mocking the username, sending the credentials
|
|
# is ignored, so with the correct password this succeeds
|
|
username.text = "fakeuser"
|
|
passwd.typeText("goodp")
|
|
win.find("Login", "push button").click()
|
|
lib.utils.check(lambda: con.showing)
|
|
|
|
|
|
@_vm_wrapper("uitests-vnc-socket")
|
|
def testConsoleVNCSocket(app, dom):
|
|
ignore = dom
|
|
win = app.topwin
|
|
con = win.find("console-gfx-viewport")
|
|
lib.utils.check(lambda: con.showing)
|
|
|
|
def _click_textconsole_menu(msg):
|
|
vmenu = win.find("^View$", "menu")
|
|
vmenu.click()
|
|
tmenu = win.find("Consoles", "menu")
|
|
tmenu.point()
|
|
app.sleep(.5) # give console menu time to dynamically populate
|
|
tmenu.find(msg, "radio menu item").click()
|
|
|
|
# A bit of an extra test, make sure selecting Graphical Console works
|
|
_click_textconsole_menu("Serial 1")
|
|
lib.utils.check(lambda: not con.showing)
|
|
_click_textconsole_menu("Graphical Console")
|
|
lib.utils.check(lambda: con.showing)
|
|
|
|
|
|
@_vm_wrapper("uitests-spice-standard")
|
|
def testConsoleAutoconnect(app, dom):
|
|
ignore = dom
|
|
win = app.topwin
|
|
con = win.find("console-gfx-viewport")
|
|
lib.utils.check(lambda: con.showing)
|
|
|
|
# Disable autoconnect
|
|
vmenu = win.find("^View$", "menu")
|
|
vmenu.click()
|
|
vmenu.find("Autoconnect").click()
|
|
dom.destroy()
|
|
label = win.find("Guest is not running.")
|
|
label.check_onscreen()
|
|
dom.create()
|
|
label.check_not_onscreen()
|
|
button = win.find("Connect to console", "push button")
|
|
button.check_onscreen()
|
|
lib.utils.check(lambda: not con.showing)
|
|
button.click()
|
|
lib.utils.check(lambda: con.showing)
|
|
|
|
|
|
@_vm_wrapper("uitests-lxc-serial", uri="lxc:///")
|
|
def testConsoleLXCSerial(app, dom):
|
|
"""
|
|
Ensure LXC has serial open, and we can send some data
|
|
"""
|
|
win = app.topwin
|
|
term = win.find("Serial Terminal")
|
|
lib.utils.check(lambda: term.showing)
|
|
term.typeText("help\n")
|
|
lib.utils.check(lambda: "COMMANDS" in term.text)
|
|
|
|
term.doubleClick()
|
|
term.click(button=3)
|
|
menu = app.root.find("serial-popup-menu")
|
|
menu.find("Copy", "menu item").click()
|
|
|
|
term.click()
|
|
term.click(button=3)
|
|
menu = app.root.find("serial-popup-menu")
|
|
menu.find("Paste", "menu item").click()
|
|
|
|
win.find("Details", "radio button").click()
|
|
win.find("Console", "radio button").click()
|
|
_destroy(app, win)
|
|
|
|
# Restart the guest to trigger reconnect code
|
|
win.find("Run", "push button").click()
|
|
term = win.find("Serial Terminal")
|
|
lib.utils.check(lambda: term.showing)
|
|
|
|
# Ensure ctrl+w doesn't close the window, modifiers are disabled
|
|
term.click()
|
|
win.keyCombo("<ctrl><shift>w")
|
|
lib.utils.check(lambda: win.showing)
|
|
# Shut it down, ensure accelerator works again
|
|
_destroy(app, win)
|
|
lib.utils.check(lambda: not dom.isActive())
|
|
win.click_title()
|
|
app.sleep(.3) # make sure window code has time to adjust modifiers
|
|
win.keyCombo("<ctrl><shift>w")
|
|
lib.utils.check(lambda: not win.showing)
|
|
|
|
|
|
@_vm_wrapper("uitests-spice-specific")
|
|
def testConsoleSpiceSpecific(app, dom):
|
|
"""
|
|
Spice specific behavior. Has lots of devices that will open
|
|
channels, spice GL + local config, and usbredir
|
|
"""
|
|
ignore = dom
|
|
win = app.topwin
|
|
con = win.find("console-gfx-viewport")
|
|
lib.utils.check(lambda: con.showing)
|
|
|
|
# Just ensure the dialog pops up, can't really test much more
|
|
# than that
|
|
win.find("Virtual Machine", "menu").click()
|
|
win.find("Redirect USB", "menu item").click()
|
|
|
|
usbwin = app.root.find("vmm dialog", "alert")
|
|
usbwin.find("Select USB devices for redirection", "label")
|
|
usbwin.find("SPICE CD", "check box").click()
|
|
chooser = app.root.find(None, "file chooser")
|
|
# Find the cwd bookmark on the left
|
|
chooser.find("virt-manager", "label").click()
|
|
chooser.find("virt-manager", "label").click()
|
|
chooser.find("COPYING").click()
|
|
app.rawinput.pressKey("Enter")
|
|
lib.utils.check(lambda: not chooser.showing)
|
|
usbwin.find("Close", "push button").click()
|
|
|
|
# Test fake guest resize behavior
|
|
def _click_auto():
|
|
vmenu = win.find("^View$", "menu")
|
|
vmenu.click()
|
|
smenu = vmenu.find("Scale Display", "menu")
|
|
smenu.point()
|
|
smenu.find("Auto resize VM", "check menu item").click()
|
|
_click_auto()
|
|
win.click_title()
|
|
win.window_maximize()
|
|
_click_auto()
|
|
win.click_title()
|
|
win.click_title()
|
|
|
|
|
|
@_vm_wrapper("uitests-vnc-standard")
|
|
def testVNCSpecific(app, dom):
|
|
from gi.repository import GtkVnc
|
|
if not hasattr(GtkVnc.Display, "set_allow_resize"):
|
|
pytest.skip("GtkVnc is too old")
|
|
|
|
ignore = dom
|
|
win = app.topwin
|
|
con = win.find("console-gfx-viewport")
|
|
lib.utils.check(lambda: con.showing)
|
|
|
|
# Test guest resize behavior
|
|
def _click_auto():
|
|
vmenu = win.find("^View$", "menu")
|
|
vmenu.click()
|
|
smenu = vmenu.find("Scale Display", "menu")
|
|
smenu.point()
|
|
smenu.find("Auto resize VM", "check menu item").click()
|
|
_click_auto()
|
|
win.click_title()
|
|
win.window_maximize()
|
|
_click_auto()
|
|
win.click_title()
|
|
win.click_title()
|
|
|
|
|
|
@_vm_wrapper("uitests-hotplug")
|
|
@_create_qcow2_file
|
|
def testLiveHotplug(fname, app, dom):
|
|
"""
|
|
Live test for basic hotplugging and media change, as well as
|
|
testing our auto-poolify magic
|
|
"""
|
|
ignore = dom
|
|
win = app.topwin
|
|
win.find("Details", "radio button").click()
|
|
|
|
# Add a scsi disk, importing the passed path
|
|
win.find("add-hardware", "push button").click()
|
|
addhw = app.find_window("Add New Virtual Hardware")
|
|
addhw.find("Storage", "table cell").click()
|
|
tab = addhw.find("storage-tab", None)
|
|
lib.utils.check(lambda: tab.showing)
|
|
tab.find("Select or create", "radio button").click()
|
|
tab.find("storage-entry").set_text(fname)
|
|
tab.combo_select("Bus type:", "SCSI")
|
|
addhw.find("Finish", "push button").click()
|
|
|
|
# Verify permission dialog pops up, ask to change
|
|
app.click_alert_button(
|
|
"The emulator may not have search permissions", "Yes")
|
|
|
|
# Verify no errors
|
|
lib.utils.check(lambda: not addhw.showing)
|
|
lib.utils.check(lambda: win.active)
|
|
|
|
# Hot unplug the disk
|
|
win.find("SCSI Disk 1", "table cell").click()
|
|
tab = win.find("disk-tab", None)
|
|
lib.utils.check(lambda: tab.showing)
|
|
win.find("config-remove").click()
|
|
delete = app.find_window("Remove Disk")
|
|
delete.find_fuzzy("Delete", "button").click()
|
|
lib.utils.check(lambda: not delete.active)
|
|
lib.utils.check(lambda: os.path.exists(fname))
|
|
|
|
# Change CDROM
|
|
win.find("IDE CDROM 1", "table cell").click()
|
|
tab = win.find("disk-tab", None)
|
|
entry = win.find("media-entry")
|
|
appl = win.find("config-apply")
|
|
lib.utils.check(lambda: tab.showing)
|
|
entry.set_text(fname)
|
|
appl.click()
|
|
|
|
lib.utils.check(lambda: not appl.sensitive)
|
|
lib.utils.check(lambda: entry.text == fname)
|
|
entry.click_secondary_icon()
|
|
|
|
appl.click()
|
|
lib.utils.check(lambda: not appl.sensitive)
|
|
lib.utils.check(lambda: not entry.text)
|
|
|
|
|
|
|
|
@_vm_wrapper("uitests-hotplug")
|
|
@_create_qcow2_file
|
|
def testLiveExternalSnapshots(fname, app, dom):
|
|
win = app.topwin
|
|
win.find("Details", "radio button").click()
|
|
|
|
# Add a scsi disk, importing the passed path
|
|
win.find("add-hardware", "push button").click()
|
|
addhw = app.find_window("Add New Virtual Hardware")
|
|
addhw.find("Storage", "table cell").click()
|
|
tab = addhw.find("storage-tab", None)
|
|
lib.utils.check(lambda: tab.showing)
|
|
tab.find("Select or create", "radio button").click()
|
|
tab.find("storage-entry").set_text(fname)
|
|
tab.combo_select("Bus type:", "SCSI")
|
|
addhw.find("Finish", "push button").click()
|
|
|
|
# Verify permission dialog pops up, ask to change
|
|
app.click_alert_button(
|
|
"The emulator may not have search permissions", "Yes")
|
|
|
|
# Verify no errors
|
|
lib.utils.check(lambda: not addhw.showing)
|
|
lib.utils.check(lambda: win.active)
|
|
|
|
def _make_snapshot(name, auto=True):
|
|
win.find("snapshot-add", "push button").click()
|
|
newwin = app.find_window("Create snapshot")
|
|
newwin.find("Name:", "text").set_text(name)
|
|
external = newwin.find("external", "radio button")
|
|
if not external.isChecked:
|
|
pytest.skip("libvirt is too old for external snapshots")
|
|
if not auto:
|
|
newwin.find("auto", "check box").click()
|
|
newwin.find("Finish", "push button").click()
|
|
lib.utils.check(lambda: not newwin.showing)
|
|
newc = win.find(name, "table cell")
|
|
lib.utils.check(lambda: newc.state_selected)
|
|
|
|
win.find("Snapshots", "radio button").click()
|
|
_make_snapshot("testnewsnap1")
|
|
_make_snapshot("testnewsnap2", auto=False)
|
|
|
|
# Poweroff VM and create an offline one
|
|
run = win.find("Run", "push button")
|
|
dom.destroy()
|
|
lib.utils.check(lambda: run.sensitive)
|
|
|
|
_make_snapshot("testnewsnap-offline")
|
|
|
|
# Delete first snapshot
|
|
newc = win.find("testnewsnap1", "table cell")
|
|
newc.click()
|
|
lib.utils.check(lambda: newc.state_selected)
|
|
win.find("snapshot-delete").click()
|
|
app.click_alert_button("permanently delete", "Yes")
|
|
lib.utils.check(lambda: newc.dead, timeout=10)
|
|
lib.utils.check(lambda: win.active)
|
|
|
|
# Ensure VM is still offline
|
|
lib.utils.check(lambda: run.sensitive)
|
|
|
|
|
|
@_vm_wrapper("uitests-firmware-efi")
|
|
def testFirmwareRename(app, dom):
|
|
from virtinst import cli, DeviceDisk
|
|
win = app.topwin
|
|
dom.destroy()
|
|
|
|
# First we refresh the 'nvram' pool, so we can reliably
|
|
# check if nvram files are created/deleted as expected
|
|
conn = cli.getConnection(app.conn.getURI())
|
|
guest = virtinst.Guest(conn, dom.XMLDesc(0))
|
|
origname = dom.name()
|
|
origpath = guest.os.nvram
|
|
if not origpath:
|
|
pytest.skip("libvirt is too old to put nvram path in inactive XML")
|
|
nvramdir = os.path.dirname(origpath)
|
|
|
|
fakedisk = DeviceDisk(conn)
|
|
fakedisk.set_source_path(nvramdir + "/FAKE-UITEST-FILE")
|
|
nvram_pool = fakedisk.get_parent_pool()
|
|
nvram_pool.refresh()
|
|
|
|
newname = "uitests-firmware-efi-renamed"
|
|
newpath = origpath.replace(origname + "_VARS", newname + "_VARS")
|
|
assert DeviceDisk.path_definitely_exists(app.conn, origpath)
|
|
assert not DeviceDisk.path_definitely_exists(app.conn, newpath)
|
|
|
|
# Now do the actual UI clickage
|
|
win.find("Details", "radio button").click()
|
|
win.find("Hypervisor Details", "label")
|
|
win.find("Overview", "table cell").click()
|
|
|
|
newname = "uitests-firmware-efi-renamed"
|
|
win.find("Name:", "text").set_text(newname)
|
|
appl = win.find("config-apply")
|
|
appl.click()
|
|
lib.utils.check(lambda: not appl.sensitive)
|
|
|
|
# Confirm window was updated
|
|
app.find_window("%s on" % newname)
|
|
|
|
# Confirm nvram paths were altered as expected
|
|
assert not DeviceDisk.path_definitely_exists(app.conn, origpath)
|
|
assert DeviceDisk.path_definitely_exists(app.conn, newpath)
|