Skip to content

Commit

Permalink
Merge 1326253 into 12f651a
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Feb 4, 2019
2 parents 12f651a + 1326253 commit c077c1c
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 31 deletions.
16 changes: 16 additions & 0 deletions src/lib/y2configuration_management/salt/form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,22 @@ def keyed?
prototype.elements.any? { |e| e.respond_to?(:collection_key?) && e.collection_key? }
end

# Determines whether the collection is an scalar one
#
# @return [Boolean] true if the collection is an scalar one; false otherwise
def scalar?
return false if prototype.nil?
prototype.is_a?(FormInput) && prototype.type != :key_value
end

# Determines whether the collection is a hash with scalar values
#
# @return [Boolean] true if the collection is a hash with scalar values; false otherwise
def keyed_scalar?
return false if prototype.nil?
prototype.is_a?(FormInput) && prototype.type == :key_value
end

private

# Return a single or group of {FormElement}s based on the prototype given
Expand Down
11 changes: 11 additions & 0 deletions src/lib/y2configuration_management/salt/form_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ def collection_for_pillar(collection)
return [] if first.nil?
if first.respond_to?(:key?) && first.key?("$key")
hash_collection_for_pillar(collection)
elsif first.respond_to?(:key?) && first.key?("$value")
scalar_collection_for_pillar(collection)
else
collection.map { |d| data_for_pillar(d) }
end
Expand All @@ -186,6 +188,15 @@ def hash_collection_for_pillar(collection)
end
end

# Converts a collection into an array to be used in a Pillar
#
# @param collection [Array<Hash>] This method expects an array containing hashes which include
# `$value` element.
# @return [Array]
def scalar_collection_for_pillar(collection)
collection.map { |i| i["$value"] }
end

# Convenience method which converts a value to be used as key for a array or a hash
#
# @param key [String,Symbol,Integer]
Expand Down
32 changes: 19 additions & 13 deletions src/lib/y2configuration_management/salt/form_data_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,27 @@ module Salt
#
# There might be different kind of collections:
#
# * Array with simple values (strings, integers, etc).
# * Array of hashes. They allow a more complex collection.
# * Hash based collections which index is provided by the user.
# * (1) Array with simple values (strings, integers, etc).
# * (2) Hash based collections which index is provided by the user.
# * (3) Array of hashes. They allow a more complex collection.
#
# To simplify things in the UI layer, all collections are handled as arrays so, in the third
# case, some conversion is needed. Given an specification with three fields `$key`, `url`,
# and `license`, the collection would be stored in the Pillar like this:
# To simplify things in the UI layer, all collections are handled as arrays of hashes so, in (1)
# and (2) cases, some conversion is needed.
#
# For (1), the data in the Pillar is just an array of simple values (numbers, strings, or
# any other scalar value). Internally, it is converted to an array of hashes with just a
# `$value` key:
#
# [{ "$value" => "foo" }, { "$value" => "bar" }]
#
# In the (2) case, given an specification with three fields `$key`, `url`, and `license`, the
# collection would be stored in the Pillar like this:
#
# { "yast2" =>
# { "url" => "https://yast.opensuse.org", "license" => "GPL" }
# }
#
# Internally, it will be handled as an array:
# But internally, it will be handled as an array:
#
# [{ "$key" => "yast2", "url" => "https://yast.opensuse.org", "license" => "GPL" }]
#
Expand Down Expand Up @@ -122,12 +130,10 @@ def collection_from_pillar(data, locator)
element = form.find_element_by(locator: locator.unbounded)
if element.keyed?
data.map { |k, v| { "$key" => k }.merge(hash_from_pillar(v, locator.join(k))) }
elsif element.prototype.is_a?(FormInput)
if element.prototype.type == :key_value
data.map { |k, v| { "$key" => k, "$value" => v } }
else
data
end
elsif element.keyed_scalar?
data.map { |k, v| { "$key" => k, "$value" => v } }
elsif element.scalar?
data.map { |v| { "$value" => v } }
else
data.map { |d| hash_from_pillar(d, locator) }
end
Expand Down
2 changes: 2 additions & 0 deletions src/lib/y2configuration_management/widgets/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ def format_value(val)
def format_hash_item(item)
if item.keys == ["$key", "$value"]
["#{item["$key"]}: #{item["$value"]}"]
elsif item.keys == ["$value"]
[item["$value"].to_s]
else
headers_ids.map { |h| item[h] }
end
Expand Down
18 changes: 13 additions & 5 deletions src/lib/y2configuration_management/widgets/form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,16 @@ def contents
#
# @see CWM::AbstractWidget
def store
@result = scalar ? current_values.values.first : current_values
@result = current_values
end

# Returns widget's content
#
# @return [Hash,nil] values including the ones from the underlying widgets; nil when
# the widget has been removed from the UI.
# @return [Hash] values including the ones from the underlying widgets; values are
# `nil` when the form has been removed from the UI.
def current_values
children.reduce({}) { |a, e| a.merge(e.id => e.value) }
return children_values unless scalar?
{ "$value" => children_values.values.first }
end

# Refreshes the widget's content
Expand Down Expand Up @@ -149,6 +150,13 @@ def scalar?

private

# Returns children values
#
# @return [Hash] Hash containing the children ids and their values
def children_values
children.reduce({}) { |a, e| a.merge(e.id => e.value) }
end

def set_widgets_content
if scalar?
set_child_content
Expand All @@ -158,7 +166,7 @@ def set_widgets_content
end

def set_child_content
children.first.value = value
children.first.value = value["$value"]
end

def set_children_contents
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@

it "keeps it as an array" do
form_data = reader.form_data
expect(form_data.get(locator)).to eq(["Linux"])
expect(form_data.get(locator)).to eq([{ "$value" => "Linux" }])
end
end
end
Expand Down
20 changes: 15 additions & 5 deletions test/y2configuration_management/salt/form_data_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,18 +136,28 @@
end

describe "#to_h" do
let(:pillar) do
Y2ConfigurationManagement::Salt::Pillar.from_file(
FIXTURES_PATH.join("pillar", "test-formula.sls")
)
end

it "exports array collections as arrays" do
computers = form_data.to_h.dig("root", "person", "computers")
expect(computers).to eq(
[{ "brand" => "ACME", "disks" => [] }]
expect(computers).to contain_exactly(
a_hash_including("brand" => "Dell"),
a_hash_including("brand" => "Lenovo")
)
end

it "exports hash based collections as hashes" do
projects = form_data.to_h.dig("root", "person", "projects")
expect(projects).to eq(
"yast2" => { "url" => "https://yast.opensuse.org" }
)
expect(projects["yast2"]).to include("url" => "https://yast.opensuse.org")
end

it "exports scalar collections as arrays of scalar objects" do
platforms = form_data.to_h.dig("root", "person", "projects", "yast2", "platforms")
expect(platforms).to eq(["Linux"])
end
end

Expand Down
47 changes: 42 additions & 5 deletions test/y2configuration_management/salt/form_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,15 @@
end

describe Y2ConfigurationManagement::Salt::Collection do
subject(:collection) { form.find_element_by(locator: locator) }

let(:form) do
Y2ConfigurationManagement::Salt::Form.from_file(FIXTURES_PATH.join("form.yml"))
end

include_examples "Y2ConfigurationManagement::Salt::FormElement"

describe "#keyed?" do
subject(:collection) { form.find_element_by(locator: locator) }

let(:form) do
Y2ConfigurationManagement::Salt::Form.from_file(FIXTURES_PATH.join("form.yml"))
end

context "when it is a collection indexed by a key" do
let(:locator) { locator_from_string("root#person#projects") }
Expand All @@ -182,4 +183,40 @@
end
end
end

describe "#scalar?" do
context "when an scalar collection is given" do
let(:locator) { locator_from_string("root#person#projects#platforms") }

it "returns true" do
expect(collection).to be_scalar
end
end

context "when another kind of collection is given" do
let(:locator) { locator_from_string("root#person#computers") }

it "returns false" do
expect(collection).to_not be_scalar
end
end
end

describe "#keyed_scalar?" do
context "when a hash based collection with scalar values is given" do
let(:locator) { locator_from_string("root#person#projects#properties") }

it "returns true" do
expect(collection).to be_keyed_scalar
end
end

context "when another kind of collection is given" do
let(:locator) { locator_from_string("root#person#computers") }

it "returns false" do
expect(collection).to_not be_keyed_scalar
end
end
end
end
4 changes: 2 additions & 2 deletions test/y2configuration_management/widgets/form_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@
context "when using an scalar form" do
subject(:form) { described_class.new(widget, double("controller"), scalar: true) }

it "returns just a scalar value" do
expect(form.result).to eq("foobar")
it "returns a hash with a single '$value' key" do
expect(form.result).to eq("$value" => "foobar")
end
end
end
Expand Down

0 comments on commit c077c1c

Please sign in to comment.