Skip to content

Commit

Permalink
Add a DiskSelector dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Nov 27, 2017
1 parent d421e89 commit affc852
Show file tree
Hide file tree
Showing 2 changed files with 284 additions and 0 deletions.
152 changes: 152 additions & 0 deletions src/lib/autoinstall/dialogs/disk_selector.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# encoding: utf-8

# Copyright (c) [2017] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "ui/dialog"
require "y2storage"

Yast.import "Label"
Yast.import "UI"

module Y2Autoinstallation
module Dialogs
# Ask the user for which device to use
#
# This dialog will be used by the partitioning section preprocessor (see
# {Y2Autoinstallation::PartitioningPreprocessor}) in order to determine
# which device to use for a given <drive> section.
class DiskSelector < UI::Dialog
# @return [Y2Storage::Devicegraph] Devicegraph used to find disks
attr_reader :devicegraph
# @return [Array<String>] Device names that should be omitted
attr_reader :blacklist

# Constructor
#
# @param devicegraph [Y2Storage::Devicegraph] Devicegraph used to find disks.
# By default, the probed devicegraph is used.
# @param blacklist [Array<String>] Device names that should be omitted.
# These disks will be filtered out.
def initialize(devicegraph = nil, blacklist: [])
@devicegraph = devicegraph || Y2Storage::StorageManager.instance.probed
@blacklist = blacklist
end

# Dialog content
#
# @return [Yast::Term] Dialog content
# @see #disks_content
# @see #empty_content
def dialog_content
options.empty? ? empty_content : disks_content
end

# Dialog content when some disks are available
#
# @return [Yast::Term] Dialog content
def disks_content
VBox(
Label(_("Choose a hard disk")),
RadioButtonGroup(
Id(:options),
VBox(*options)
),
ButtonBox(*buttons)
)
end

# Dialog content when no disks are found
#
# @return [Yast::Term]
def empty_content
VBox(
Label(_("No disks found.")),
ButtonBox(abort_button)
)
end

# Handler for the `Continue` button
def ok_handler
finish_dialog(Yast::UI::QueryWidget(Id(:options), :Value))
end

# Handler for the `Abort` button
def abort_handler
finish_dialog(:abort)
end

# Handler for the `Skip` button
def skip_handler
finish_dialog(:skip)
end

protected

# Returns a list of options containing available disks
#
# @return [Array<Yast::Term>] List of options
def options
return @options if @options
first_disk = disks.first
@options = disks.each_with_index.map do |disk, idx|
Left(RadioButton(Id(disk.name), "#{idx + 1}: #{label(disk)}", first_disk == disk))
end
end

# Returns a list of available disks in the system
#
# Blacklisted disks are filtered out.
#
# @return [Array<Y2Storage::Device>] List of disks
def disks
@disks ||= devicegraph.disk_devices.reject do |disk|
blacklist.include?(disk.name)
end
end

# Dialog buttons
#
# @return [Array<Yast::Term>]
def buttons
[
PushButton(Id(:ok), Opt(:okButton, :key_F10, :default), Yast::Label.ContinueButton),
PushButton(Id(:skip), Yast::Label.SkipButton),
abort_button
]
end

# Abort button
#
# @return [Yast::Term]
def abort_button
PushButton(Id(:abort), Opt(:cancel_button, :key_F9), Yast::Label.AbortButton)
end

# Disk label to show in the list of options
#
# @param [Y2Storage::Device] Disk
# @return [String] Label
def label(disk)
"#{disk.basename}, #{disk.hwinfo.model}, #{disk.hwinfo.vendor}"
end
end
end
end

132 changes: 132 additions & 0 deletions test/lib/dialogs/disk_selector_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#!/usr/bin/env rspec
# encoding: utf-8

# Copyright (c) [2017] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require_relative "../../test_helper"
require "autoinstall/dialogs/disk_selector"
require "ostruct"

describe Y2Autoinstallation::Dialogs::DiskSelector do
subject(:dialog) { described_class.new(devicegraph) }
extend Yast::I18n

let(:devicegraph) do
instance_double(Y2Storage::Devicegraph, disk_devices: disks)
end

let(:sda) { double("sda", name: "/dev/sda", basename: "sda", hwinfo: hwinfo) }
let(:sdb) { double("sdb", name: "/dev/sdb", basename: "sdb", hwinfo: hwinfo) }
let(:hwinfo) { OpenStruct.new(model: "Model", vendor: "Vendor") }
let(:disks) { [sda, sdb] }

before do
allow(Yast::UI).to receive(:OpenDialog).and_return(true)
allow(Yast::UI).to receive(:CloseDialog).and_return(true)
end

describe "#dialog_content" do
it "displays all options" do
expect(dialog).to receive(:RadioButton).with(Id("/dev/sda"), "1: sda, Model, Vendor", true)
expect(dialog).to receive(:RadioButton).with(Id("/dev/sdb"), "2: sdb, Model, Vendor", false)
dialog.dialog_content
end

it "displays ok, skip and abort buttons" do
expect(dialog).to receive(:PushButton).with(Id(:ok), anything, anything)
expect(dialog).to receive(:PushButton).with(Id(:skip), anything)
expect(dialog).to receive(:PushButton).with(Id(:abort), anything, anything)
dialog.dialog_content
end

context "when a disk must be omitted" do
subject(:dialog) { described_class.new(devicegraph, blacklist: ["/dev/sda"]) }

it "does not list the blacklisted disk" do
expect(dialog).to_not receive(:RadioButton).with(Id("/dev/sda"), anything)
expect(dialog).to receive(:RadioButton).with(Id("/dev/sdb"), "1: sdb, Model, Vendor", true)
dialog.dialog_content
end
end

context "when no disk are found" do
let(:disks) { [] }

it "shows an error message" do
expect(dialog).to receive(:Label).with(_("No disks found."))
dialog.dialog_content
end

it "only shows the abort button" do
expect(dialog).to_not receive(:PushButton).with(Id(:ok), anything, anything)
expect(dialog).to_not receive(:PushButton).with(Id(:skip), anything)
expect(dialog).to receive(:PushButton).with(Id(:abort), anything, anything)
dialog.dialog_content
end
end

context "when no eligible disks are found" do
subject(:dialog) { described_class.new(devicegraph, blacklist: ["/dev/sda", "/dev/sdb"]) }

it "shows an error message" do
expect(dialog).to receive(:Label).with(_("No disks found."))
dialog.dialog_content
end

it "only shows the abort button" do
expect(dialog).to_not receive(:PushButton).with(Id(:ok), anything, anything)
expect(dialog).to receive(:PushButton).with(Id(:abort), anything, anything)
dialog.dialog_content
end
end
end

describe "#run" do
before do
allow(Yast::UI).to receive(:UserInput).and_return(button)
allow(Yast::UI).to receive(:QueryWidget).with(Id(:options), :Value)
.and_return("/dev/sda")
end

context "when the user presses 'Continue'" do
let(:button) { :ok }

it "returns the selected disk" do
expect(dialog.run).to eq("/dev/sda")
end
end

context "when the user presses 'Abort'" do
let(:button) { :abort }

it "returns :abort" do
expect(dialog.run).to eq(:abort)
end
end

context "when the user presses 'Skip'" do
let(:button) { :skip }

it "returns :skip" do
expect(dialog.run).to eq(:skip)
end
end
end
end

0 comments on commit affc852

Please sign in to comment.