summaryrefslogtreecommitdiff
path: root/spec/ruby/core/data
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/data')
-rw-r--r--spec/ruby/core/data/constants_spec.rb20
-rw-r--r--spec/ruby/core/data/deconstruct_keys_spec.rb227
-rw-r--r--spec/ruby/core/data/deconstruct_spec.rb8
-rw-r--r--spec/ruby/core/data/define_spec.rb48
-rw-r--r--spec/ruby/core/data/eql_spec.rb92
-rw-r--r--spec/ruby/core/data/equal_value_spec.rb92
-rw-r--r--spec/ruby/core/data/fixtures/classes.rb23
-rw-r--r--spec/ruby/core/data/hash_spec.rb36
-rw-r--r--spec/ruby/core/data/initialize_spec.rb145
-rw-r--r--spec/ruby/core/data/inspect_spec.rb6
-rw-r--r--spec/ruby/core/data/members_spec.rb26
-rw-r--r--spec/ruby/core/data/shared/inspect.rb8
-rw-r--r--spec/ruby/core/data/to_h_spec.rb94
-rw-r--r--spec/ruby/core/data/to_s_spec.rb6
-rw-r--r--spec/ruby/core/data/with_spec.rb66
15 files changed, 501 insertions, 396 deletions
diff --git a/spec/ruby/core/data/constants_spec.rb b/spec/ruby/core/data/constants_spec.rb
index 2eb43d501e..ad0b1ddea7 100644
--- a/spec/ruby/core/data/constants_spec.rb
+++ b/spec/ruby/core/data/constants_spec.rb
@@ -1,21 +1,11 @@
require_relative '../../spec_helper'
-ruby_version_is ''...'3.2' do
- describe "Data" do
- it "does not exist anymore" do
- Object.should_not have_constant(:Data)
- end
+describe "Data" do
+ it "is a new constant" do
+ Data.superclass.should == Object
end
-end
-
-ruby_version_is '3.2' do
- describe "Data" do
- it "is a new constant" do
- Data.superclass.should == Object
- end
- it "is not deprecated" do
- -> { Data }.should_not complain
- end
+ it "is not deprecated" do
+ -> { Data }.should_not complain
end
end
diff --git a/spec/ruby/core/data/deconstruct_keys_spec.rb b/spec/ruby/core/data/deconstruct_keys_spec.rb
index 07af87771d..df378f8b98 100644
--- a/spec/ruby/core/data/deconstruct_keys_spec.rb
+++ b/spec/ruby/core/data/deconstruct_keys_spec.rb
@@ -1,107 +1,130 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data#deconstruct" do
- it "returns a hash of attributes" do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
- d.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
- end
-
- it "requires one argument" do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
-
- -> {
- d.deconstruct_keys
- }.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
- end
-
- it "returns only specified keys" do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
-
- d.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
- d.deconstruct_keys([:x] ).should == {x: 1}
- d.deconstruct_keys([] ).should == {}
- end
-
- it "accepts string attribute names" do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
- d.deconstruct_keys(['x', 'y']).should == {'x' => 1, 'y' => 2}
- end
-
- it "accepts argument position number as well but returns them as keys" do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
-
- d.deconstruct_keys([0, 1]).should == {0 => 1, 1 => 2}
- d.deconstruct_keys([0] ).should == {0 => 1}
- d.deconstruct_keys([-1] ).should == {-1 => 2}
- end
-
- it "ignores incorrect position numbers" do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
-
- d.deconstruct_keys([0, 3]).should == {0 => 1}
- end
-
- it "support mixing attribute names and argument position numbers" do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
-
- d.deconstruct_keys([0, :x]).should == {0 => 1, :x => 1}
- end
-
- it "returns an empty hash when there are more keys than attributes" do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
- d.deconstruct_keys([:x, :y, :x]).should == {}
- end
-
- it "returns at first not existing attribute name" do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
-
- d.deconstruct_keys([:a, :x]).should == {}
- d.deconstruct_keys([:x, :a]).should == {x: 1}
- end
-
- it "returns at first not existing argument position number" do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
-
- d.deconstruct_keys([3, 0]).should == {}
- d.deconstruct_keys([0, 3]).should == {0 => 1}
- end
-
- it "accepts nil argument and return all the attributes" do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
-
- d.deconstruct_keys(nil).should == {x: 1, y: 2}
- end
-
- it "raises TypeError if index is not a String, a Symbol and not convertible to Integer " do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
-
- -> {
- d.deconstruct_keys([0, []])
- }.should raise_error(TypeError, "no implicit conversion of Array into Integer")
- end
-
- it "raise TypeError if passed anything except nil or array" do
- klass = Data.define(:x, :y)
- d = klass.new(1, 2)
-
- -> { d.deconstruct_keys('x') }.should raise_error(TypeError, /expected Array or nil/)
- -> { d.deconstruct_keys(1) }.should raise_error(TypeError, /expected Array or nil/)
- -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, /expected Array or nil/)
- -> { d.deconstruct_keys({}) }.should raise_error(TypeError, /expected Array or nil/)
- end
+describe "Data#deconstruct_keys" do
+ it "returns a hash of attributes" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
+ end
+
+ it "requires one argument" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ -> {
+ d.deconstruct_keys
+ }.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
+ end
+
+ it "returns only specified keys" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
+ d.deconstruct_keys([:x] ).should == {x: 1}
+ d.deconstruct_keys([] ).should == {}
+ end
+
+ it "accepts string attribute names" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys(['x', 'y']).should == {'x' => 1, 'y' => 2}
+ end
+
+ it "accepts argument position number as well but returns them as keys" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([0, 1]).should == {0 => 1, 1 => 2}
+ d.deconstruct_keys([0] ).should == {0 => 1}
+ d.deconstruct_keys([-1] ).should == {-1 => 2}
+ end
+
+ it "ignores incorrect position numbers" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([0, 3]).should == {0 => 1}
+ end
+
+ it "support mixing attribute names and argument position numbers" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([0, :x]).should == {0 => 1, :x => 1}
+ end
+
+ it "returns an empty hash when there are more keys than attributes" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([:x, :y, :x]).should == {}
+ end
+
+ it "returns at first not existing attribute name" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([:a, :x]).should == {}
+ d.deconstruct_keys([:x, :a]).should == {x: 1}
+ end
+
+ it "returns at first not existing argument position number" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([3, 0]).should == {}
+ d.deconstruct_keys([0, 3]).should == {0 => 1}
+ end
+
+ it "accepts nil argument and return all the attributes" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys(nil).should == {x: 1, y: 2}
+ end
+
+ it "tries to convert a key with #to_int if index is not a String nor a Symbol, but responds to #to_int" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ key = mock("to_int")
+ key.should_receive(:to_int).and_return(1)
+
+ d.deconstruct_keys([key]).should == { key => 2 }
+ end
+
+ it "raises a TypeError if the conversion with #to_int does not return an Integer" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ key = mock("to_int")
+ key.should_receive(:to_int).and_return("not an Integer")
+
+ -> {
+ d.deconstruct_keys([key])
+ }.should raise_error(TypeError, /can't convert MockObject to Integer/)
+ end
+
+ it "raises TypeError if index is not a String, a Symbol and not convertible to Integer " do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ -> {
+ d.deconstruct_keys([0, []])
+ }.should raise_error(TypeError, "no implicit conversion of Array into Integer")
+ end
+
+ it "raise TypeError if passed anything except nil or array" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ -> { d.deconstruct_keys('x') }.should raise_error(TypeError, /expected Array or nil/)
+ -> { d.deconstruct_keys(1) }.should raise_error(TypeError, /expected Array or nil/)
+ -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, /expected Array or nil/)
+ -> { d.deconstruct_keys({}) }.should raise_error(TypeError, /expected Array or nil/)
end
end
diff --git a/spec/ruby/core/data/deconstruct_spec.rb b/spec/ruby/core/data/deconstruct_spec.rb
index f0995e8fed..4ca0b87039 100644
--- a/spec/ruby/core/data/deconstruct_spec.rb
+++ b/spec/ruby/core/data/deconstruct_spec.rb
@@ -1,10 +1,8 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data#deconstruct" do
- it "returns an array of attribute values" do
- DataSpecs::Measure.new(42, "km").deconstruct.should == [42, "km"]
- end
+describe "Data#deconstruct" do
+ it "returns an array of attribute values" do
+ DataSpecs::Measure.new(42, "km").deconstruct.should == [42, "km"]
end
end
diff --git a/spec/ruby/core/data/define_spec.rb b/spec/ruby/core/data/define_spec.rb
index 2aa2c50d4c..c0b4671e39 100644
--- a/spec/ruby/core/data/define_spec.rb
+++ b/spec/ruby/core/data/define_spec.rb
@@ -1,36 +1,34 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data.define" do
- it "accepts no arguments" do
- empty_data = Data.define
- empty_data.members.should == []
- end
+describe "Data.define" do
+ it "accepts no arguments" do
+ empty_data = Data.define
+ empty_data.members.should == []
+ end
- it "accepts symbols" do
- movie = Data.define(:title, :year)
- movie.members.should == [:title, :year]
- end
+ it "accepts symbols" do
+ movie = Data.define(:title, :year)
+ movie.members.should == [:title, :year]
+ end
- it "accepts strings" do
- movie = Data.define("title", "year")
- movie.members.should == [:title, :year]
- end
+ it "accepts strings" do
+ movie = Data.define("title", "year")
+ movie.members.should == [:title, :year]
+ end
- it "accepts a mix of strings and symbols" do
- movie = Data.define("title", :year, "genre")
- movie.members.should == [:title, :year, :genre]
- end
+ it "accepts a mix of strings and symbols" do
+ movie = Data.define("title", :year, "genre")
+ movie.members.should == [:title, :year, :genre]
+ end
- it "accepts a block" do
- movie = Data.define(:title, :year) do
- def title_with_year
- "#{title} (#{year})"
- end
+ it "accepts a block" do
+ movie = Data.define(:title, :year) do
+ def title_with_year
+ "#{title} (#{year})"
end
- movie.members.should == [:title, :year]
- movie.new("Matrix", 1999).title_with_year.should == "Matrix (1999)"
end
+ movie.members.should == [:title, :year]
+ movie.new("Matrix", 1999).title_with_year.should == "Matrix (1999)"
end
end
diff --git a/spec/ruby/core/data/eql_spec.rb b/spec/ruby/core/data/eql_spec.rb
index 906e46316c..6958d5de4a 100644
--- a/spec/ruby/core/data/eql_spec.rb
+++ b/spec/ruby/core/data/eql_spec.rb
@@ -1,65 +1,63 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data#eql?" do
- it "returns true if the other is the same object" do
- a = DataSpecs::Measure.new(42, "km")
- a.should.eql?(a)
- end
+describe "Data#eql?" do
+ it "returns true if the other is the same object" do
+ a = DataSpecs::Measure.new(42, "km")
+ a.should.eql?(a)
+ end
- it "returns true if the other has all the same fields" do
- a = DataSpecs::Measure.new(42, "km")
- b = DataSpecs::Measure.new(42, "km")
- a.should.eql?(b)
- end
+ it "returns true if the other has all the same fields" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "km")
+ a.should.eql?(b)
+ end
- it "returns false if the other is a different object or has different fields" do
- a = DataSpecs::Measure.new(42, "km")
- b = DataSpecs::Measure.new(42, "mi")
- a.should_not.eql?(b)
- end
+ it "returns false if the other is a different object or has different fields" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "mi")
+ a.should_not.eql?(b)
+ end
- it "returns false if other is of a different class" do
- a = DataSpecs::Measure.new(42, "km")
- klass = Data.define(*DataSpecs::Measure.members)
- b = klass.new(42, "km")
- a.should_not.eql?(b)
- end
+ it "returns false if other is of a different class" do
+ a = DataSpecs::Measure.new(42, "km")
+ klass = Data.define(*DataSpecs::Measure.members)
+ b = klass.new(42, "km")
+ a.should_not.eql?(b)
+ end
- it "returns false if any corresponding elements are not equal with #eql?" do
- a = DataSpecs::Measure.new(42, "km")
- b = DataSpecs::Measure.new(42.0, "mi")
- a.should_not.eql?(b)
- end
+ it "returns false if any corresponding elements are not equal with #eql?" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42.0, "mi")
+ a.should_not.eql?(b)
+ end
- context "recursive structure" do
- it "returns true the other is the same object" do
- a = DataSpecs::Measure.allocate
- a.send(:initialize, amount: 42, unit: a)
+ context "recursive structure" do
+ it "returns true the other is the same object" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
- a.should.eql?(a)
- end
+ a.should.eql?(a)
+ end
- it "returns true if the other has all the same fields" do
- a = DataSpecs::Measure.allocate
- a.send(:initialize, amount: 42, unit: a)
+ it "returns true if the other has all the same fields" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
- b = DataSpecs::Measure.allocate
- b.send(:initialize, amount: 42, unit: b)
+ b = DataSpecs::Measure.allocate
+ b.send(:initialize, amount: 42, unit: b)
- a.should.eql?(b)
- end
+ a.should.eql?(b)
+ end
- it "returns false if any corresponding elements are not equal with #eql?" do
- a = DataSpecs::Measure.allocate
- a.send(:initialize, amount: a, unit: "km")
+ it "returns false if any corresponding elements are not equal with #eql?" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: a, unit: "km")
- b = DataSpecs::Measure.allocate
- b.send(:initialize, amount: b, unit: "mi")
+ b = DataSpecs::Measure.allocate
+ b.send(:initialize, amount: b, unit: "mi")
- a.should_not.eql?(b)
- end
+ a.should_not.eql?(b)
end
end
end
diff --git a/spec/ruby/core/data/equal_value_spec.rb b/spec/ruby/core/data/equal_value_spec.rb
index f90a7d7a62..d9a0dcff3e 100644
--- a/spec/ruby/core/data/equal_value_spec.rb
+++ b/spec/ruby/core/data/equal_value_spec.rb
@@ -1,65 +1,63 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data#==" do
- it "returns true if the other is the same object" do
- a = DataSpecs::Measure.new(42, "km")
- a.should == a
- end
+describe "Data#==" do
+ it "returns true if the other is the same object" do
+ a = DataSpecs::Measure.new(42, "km")
+ a.should == a
+ end
- it "returns true if the other has all the same fields" do
- a = DataSpecs::Measure.new(42, "km")
- b = DataSpecs::Measure.new(42, "km")
- a.should == b
- end
+ it "returns true if the other has all the same fields" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "km")
+ a.should == b
+ end
- it "returns false if the other is a different object or has different fields" do
- a = DataSpecs::Measure.new(42, "km")
- b = DataSpecs::Measure.new(42, "mi")
- a.should_not == b
- end
+ it "returns false if the other is a different object or has different fields" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "mi")
+ a.should_not == b
+ end
- it "returns false if other is of a different class" do
- a = DataSpecs::Measure.new(42, "km")
- klass = Data.define(*DataSpecs::Measure.members)
- b = klass.new(42, "km")
- a.should_not == b
- end
+ it "returns false if other is of a different class" do
+ a = DataSpecs::Measure.new(42, "km")
+ klass = Data.define(*DataSpecs::Measure.members)
+ b = klass.new(42, "km")
+ a.should_not == b
+ end
- it "returns false if any corresponding elements are not equal with #==" do
- a = DataSpecs::Measure.new(42, "km")
- b = DataSpecs::Measure.new(42.0, "mi")
- a.should_not == b
- end
+ it "returns false if any corresponding elements are not equal with #==" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42.0, "mi")
+ a.should_not == b
+ end
- context "recursive structure" do
- it "returns true the other is the same object" do
- a = DataSpecs::Measure.allocate
- a.send(:initialize, amount: 42, unit: a)
+ context "recursive structure" do
+ it "returns true the other is the same object" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
- a.should == a
- end
+ a.should == a
+ end
- it "returns true if the other has all the same fields" do
- a = DataSpecs::Measure.allocate
- a.send(:initialize, amount: 42, unit: a)
+ it "returns true if the other has all the same fields" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
- b = DataSpecs::Measure.allocate
- b.send(:initialize, amount: 42, unit: b)
+ b = DataSpecs::Measure.allocate
+ b.send(:initialize, amount: 42, unit: b)
- a.should == b
- end
+ a.should == b
+ end
- it "returns false if any corresponding elements are not equal with #==" do
- a = DataSpecs::Measure.allocate
- a.send(:initialize, amount: a, unit: "km")
+ it "returns false if any corresponding elements are not equal with #==" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: a, unit: "km")
- b = DataSpecs::Measure.allocate
- b.send(:initialize, amount: b, unit: "mi")
+ b = DataSpecs::Measure.allocate
+ b.send(:initialize, amount: b, unit: "mi")
- a.should_not == b
- end
+ a.should_not == b
end
end
end
diff --git a/spec/ruby/core/data/fixtures/classes.rb b/spec/ruby/core/data/fixtures/classes.rb
index f0a526517d..650c0b2a62 100644
--- a/spec/ruby/core/data/fixtures/classes.rb
+++ b/spec/ruby/core/data/fixtures/classes.rb
@@ -1,5 +1,5 @@
module DataSpecs
- guard -> { ruby_version_is "3.2" and Data.respond_to?(:define) } do
+ if Data.respond_to?(:define)
Measure = Data.define(:amount, :unit)
class MeasureWithOverriddenName < Measure
@@ -9,5 +9,26 @@ module DataSpecs
end
class DataSubclass < Data; end
+
+ MeasureSubclass = Class.new(Measure) do
+ def initialize(amount:, unit:)
+ super
+ end
+ end
+
+ Empty = Data.define()
+
+ DataWithOverriddenInitialize = Data.define(:amount, :unit) do
+ def initialize(*rest, **kw)
+ super
+ ScratchPad.record [:initialize, rest, kw]
+ end
+ end
+
+ Area = Data.define(:width, :height, :area) do
+ def initialize(width:, height:)
+ super(width: width, height: height, area: width * height)
+ end
+ end
end
end
diff --git a/spec/ruby/core/data/hash_spec.rb b/spec/ruby/core/data/hash_spec.rb
index 324a2abca4..c23f08a71d 100644
--- a/spec/ruby/core/data/hash_spec.rb
+++ b/spec/ruby/core/data/hash_spec.rb
@@ -1,27 +1,25 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data#hash" do
- it "returns the same integer for objects with the same content" do
- a = DataSpecs::Measure.new(42, "km")
- b = DataSpecs::Measure.new(42, "km")
- a.hash.should == b.hash
- a.hash.should be_an_instance_of(Integer)
- end
+describe "Data#hash" do
+ it "returns the same integer for objects with the same content" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "km")
+ a.hash.should == b.hash
+ a.hash.should be_an_instance_of(Integer)
+ end
- it "returns different hashes for objects with different values" do
- a = DataSpecs::Measure.new(42, "km")
- b = DataSpecs::Measure.new(42, "ml")
- a.hash.should_not == b.hash
+ it "returns different hashes for objects with different values" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "ml")
+ a.hash.should_not == b.hash
- a = DataSpecs::Measure.new(42, "km")
- b = DataSpecs::Measure.new(13, "km")
- a.hash.should_not == b.hash
- end
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(13, "km")
+ a.hash.should_not == b.hash
+ end
- it "returns different hashes for different classes" do
- Data.define(:x).new(1).hash.should != Data.define(:x).new(1).hash
- end
+ it "returns different hashes for different classes" do
+ Data.define(:x).new(1).hash.should != Data.define(:x).new(1).hash
end
end
diff --git a/spec/ruby/core/data/initialize_spec.rb b/spec/ruby/core/data/initialize_spec.rb
index 2c36bd3ac4..010c73b91b 100644
--- a/spec/ruby/core/data/initialize_spec.rb
+++ b/spec/ruby/core/data/initialize_spec.rb
@@ -1,65 +1,124 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data#initialize" do
- it "accepts positional arguments" do
- data = DataSpecs::Measure.new(42, "km")
+describe "Data#initialize" do
+ it "accepts positional arguments" do
+ data = DataSpecs::Measure.new(42, "km")
- data.amount.should == 42
- data.unit.should == "km"
- end
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
- it "accepts alternative positional arguments" do
- data = DataSpecs::Measure[42, "km"]
+ it "accepts alternative positional arguments" do
+ data = DataSpecs::Measure[42, "km"]
- data.amount.should == 42
- data.unit.should == "km"
- end
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
- it "accepts keyword arguments" do
- data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ it "accepts keyword arguments" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
- data.amount.should == 42
- data.unit.should == "km"
- end
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
+
+ it "accepts alternative keyword arguments" do
+ data = DataSpecs::Measure[amount: 42, unit: "km"]
- it "accepts alternative keyword arguments" do
- data = DataSpecs::Measure[amount: 42, unit: "km"]
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
+
+ it "accepts String keyword arguments" do
+ data = DataSpecs::Measure.new("amount" => 42, "unit" => "km")
+
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
- data.amount.should == 42
- data.unit.should == "km"
+ it "raises ArgumentError if no arguments are given" do
+ -> {
+ DataSpecs::Measure.new
+ }.should raise_error(ArgumentError) { |e|
+ e.message.should.include?("missing keywords: :amount, :unit")
+ }
+ end
+
+ it "raises ArgumentError if at least one argument is missing" do
+ -> {
+ DataSpecs::Measure.new(unit: "km")
+ }.should raise_error(ArgumentError) { |e|
+ e.message.should.include?("missing keyword: :amount")
+ }
+ end
+
+ it "raises ArgumentError if unknown keyword is given" do
+ -> {
+ DataSpecs::Measure.new(amount: 42, unit: "km", system: "metric")
+ }.should raise_error(ArgumentError) { |e|
+ e.message.should.include?("unknown keyword: :system")
+ }
+ end
+
+ it "supports super from a subclass" do
+ ms = DataSpecs::MeasureSubclass.new(amount: 1, unit: "km")
+
+ ms.amount.should == 1
+ ms.unit.should == "km"
+ end
+
+ it "supports Data with no fields" do
+ -> { DataSpecs::Empty.new }.should_not raise_error
+ end
+
+ it "can be overridden" do
+ ScratchPad.record []
+
+ measure_class = Data.define(:amount, :unit) do
+ def initialize(*, **)
+ super
+ ScratchPad << :initialize
+ end
end
- it "accepts String keyword arguments" do
- data = DataSpecs::Measure.new("amount" => 42, "unit" => "km")
+ measure_class.new(42, "m")
+ ScratchPad.recorded.should == [:initialize]
+ end
+
+ context "when it is overridden" do
+ it "is called with keyword arguments when given positional arguments" do
+ ScratchPad.clear
+ DataSpecs::DataWithOverriddenInitialize.new(42, "m")
+ ScratchPad.recorded.should == [:initialize, [], {amount: 42, unit: "m"}]
+ end
- data.amount.should == 42
- data.unit.should == "km"
+ it "is called with keyword arguments when given keyword arguments" do
+ ScratchPad.clear
+ DataSpecs::DataWithOverriddenInitialize.new(amount: 42, unit: "m")
+ ScratchPad.recorded.should == [:initialize, [], {amount: 42, unit: "m"}]
end
- it "raises ArgumentError if no arguments are given" do
- -> {
- DataSpecs::Measure.new
- }.should raise_error(ArgumentError) { |e|
- e.message.should.include?("missing keywords: :amount, :unit")
- }
+ it "is called with keyword arguments when given alternative positional arguments" do
+ ScratchPad.clear
+ DataSpecs::DataWithOverriddenInitialize[42, "m"]
+ ScratchPad.recorded.should == [:initialize, [], {amount: 42, unit: "m"}]
end
- it "raises ArgumentError if at least one argument is missing" do
- -> {
- DataSpecs::Measure.new(unit: "km")
- }.should raise_error(ArgumentError) { |e|
- e.message.should.include?("missing keyword: :amount")
- }
+ it "is called with keyword arguments when given alternative keyword arguments" do
+ ScratchPad.clear
+ DataSpecs::DataWithOverriddenInitialize[amount: 42, unit: "m"]
+ ScratchPad.recorded.should == [:initialize, [], {amount: 42, unit: "m"}]
end
- it "raises ArgumentError if unknown keyword is given" do
- -> {
- DataSpecs::Measure.new(amount: 42, unit: "km", system: "metric")
- }.should raise_error(ArgumentError) { |e|
- e.message.should.include?("unknown keyword: :system")
- }
+ # See https://github.com/ruby/psych/pull/765
+ it "can be deserialized by calling Data.instance_method(:initialize)" do
+ d1 = DataSpecs::Area.new(width: 2, height: 3)
+ d1.area.should == 6
+
+ d2 = DataSpecs::Area.allocate
+ Data.instance_method(:initialize).bind_call(d2, **d1.to_h)
+ d2.should == d1
end
end
end
diff --git a/spec/ruby/core/data/inspect_spec.rb b/spec/ruby/core/data/inspect_spec.rb
index 3d337fac68..38642910a0 100644
--- a/spec/ruby/core/data/inspect_spec.rb
+++ b/spec/ruby/core/data/inspect_spec.rb
@@ -1,8 +1,6 @@
require_relative '../../spec_helper'
require_relative 'shared/inspect'
-ruby_version_is "3.2" do
- describe "Data#inspect" do
- it_behaves_like :data_inspect, :inspect
- end
+describe "Data#inspect" do
+ it_behaves_like :data_inspect, :inspect
end
diff --git a/spec/ruby/core/data/members_spec.rb b/spec/ruby/core/data/members_spec.rb
index 1776b0b9c1..457a90a0d6 100644
--- a/spec/ruby/core/data/members_spec.rb
+++ b/spec/ruby/core/data/members_spec.rb
@@ -1,23 +1,21 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data#members" do
- it "returns an array of attribute names" do
- measure = DataSpecs::Measure.new(amount: 42, unit: 'km')
- measure.members.should == [:amount, :unit]
- end
+describe "Data#members" do
+ it "returns an array of attribute names" do
+ measure = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ measure.members.should == [:amount, :unit]
end
+end
- describe "DataClass#members" do
- it "returns an array of attribute names" do
- DataSpecs::Measure.members.should == [:amount, :unit]
- end
+describe "DataClass#members" do
+ it "returns an array of attribute names" do
+ DataSpecs::Measure.members.should == [:amount, :unit]
+ end
- context "class inheriting Data" do
- it "isn't available in a subclass" do
- DataSpecs::DataSubclass.should_not.respond_to?(:members)
- end
+ context "class inheriting Data" do
+ it "isn't available in a subclass" do
+ DataSpecs::DataSubclass.should_not.respond_to?(:members)
end
end
end
diff --git a/spec/ruby/core/data/shared/inspect.rb b/spec/ruby/core/data/shared/inspect.rb
index 7f54a46de3..6cd5664da7 100644
--- a/spec/ruby/core/data/shared/inspect.rb
+++ b/spec/ruby/core/data/shared/inspect.rb
@@ -50,5 +50,13 @@ describe :data_inspect, shared: true do
a.send(@method).should == "#<data DataSpecs::Measure amount=42, unit=#<data DataSpecs::Measure:...>>"
end
+
+ it "returns string representation with recursive attribute replaced with ... when an anonymous class" do
+ klass = Class.new(DataSpecs::Measure)
+ a = klass.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ a.send(@method).should =~ /#<data amount=42, unit=#<data #<Class:0x.+?>:\.\.\.>>/
+ end
end
end
diff --git a/spec/ruby/core/data/to_h_spec.rb b/spec/ruby/core/data/to_h_spec.rb
index 41d6960c97..64816b7251 100644
--- a/spec/ruby/core/data/to_h_spec.rb
+++ b/spec/ruby/core/data/to_h_spec.rb
@@ -1,65 +1,63 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data#to_h" do
- it "transforms the data object into a hash" do
+describe "Data#to_h" do
+ it "transforms the data object into a hash" do
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ data.to_h.should == { amount: 42, unit: 'km' }
+ end
+
+ context "with block" do
+ it "transforms [key, value] pairs returned by the block into a hash" do
data = DataSpecs::Measure.new(amount: 42, unit: 'km')
- data.to_h.should == { amount: 42, unit: 'km' }
+ data.to_h { |key, value| [value, key] }.should == { 42 => :amount, 'km' => :unit }
end
- context "with block" do
- it "transforms [key, value] pairs returned by the block into a hash" do
- data = DataSpecs::Measure.new(amount: 42, unit: 'km')
- data.to_h { |key, value| [value, key] }.should == { 42 => :amount, 'km' => :unit }
- end
-
- it "passes to a block each pair's key and value as separate arguments" do
- ScratchPad.record []
- data = DataSpecs::Measure.new(amount: 42, unit: 'km')
- data.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
- ScratchPad.recorded.sort.should == [[:amount, 42], [:unit, 'km']]
+ it "passes to a block each pair's key and value as separate arguments" do
+ ScratchPad.record []
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ data.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
+ ScratchPad.recorded.sort.should == [[:amount, 42], [:unit, 'km']]
- ScratchPad.record []
- data.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
- ScratchPad.recorded.sort.should == [[:amount, 42], [:unit, 'km']]
- end
+ ScratchPad.record []
+ data.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [[:amount, 42], [:unit, 'km']]
+ end
- it "raises ArgumentError if block returns longer or shorter array" do
- data = DataSpecs::Measure.new(amount: 42, unit: 'km')
- -> do
- data.to_h { |k, v| [k.to_s, v*v, 1] }
- end.should raise_error(ArgumentError, /element has wrong array length/)
+ it "raises ArgumentError if block returns longer or shorter array" do
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ -> do
+ data.to_h { |k, v| [k.to_s, v*v, 1] }
+ end.should raise_error(ArgumentError, /element has wrong array length/)
- -> do
- data.to_h { |k, v| [k] }
- end.should raise_error(ArgumentError, /element has wrong array length/)
- end
+ -> do
+ data.to_h { |k, v| [k] }
+ end.should raise_error(ArgumentError, /element has wrong array length/)
+ end
- it "raises TypeError if block returns something other than Array" do
- data = DataSpecs::Measure.new(amount: 42, unit: 'km')
- -> do
- data.to_h { |k, v| "not-array" }
- end.should raise_error(TypeError, /wrong element type String/)
- end
+ it "raises TypeError if block returns something other than Array" do
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ -> do
+ data.to_h { |k, v| "not-array" }
+ end.should raise_error(TypeError, /wrong element type String/)
+ end
- it "coerces returned pair to Array with #to_ary" do
- x = mock('x')
- x.stub!(:to_ary).and_return([:b, 'b'])
- data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ it "coerces returned pair to Array with #to_ary" do
+ x = mock('x')
+ x.stub!(:to_ary).and_return([:b, 'b'])
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
- data.to_h { |k| x }.should == { :b => 'b' }
- end
+ data.to_h { |k| x }.should == { :b => 'b' }
+ end
- it "does not coerce returned pair to Array with #to_a" do
- x = mock('x')
- x.stub!(:to_a).and_return([:b, 'b'])
- data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ it "does not coerce returned pair to Array with #to_a" do
+ x = mock('x')
+ x.stub!(:to_a).and_return([:b, 'b'])
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
- -> do
- data.to_h { |k| x }
- end.should raise_error(TypeError, /wrong element type MockObject/)
- end
+ -> do
+ data.to_h { |k| x }
+ end.should raise_error(TypeError, /wrong element type MockObject/)
end
end
end
diff --git a/spec/ruby/core/data/to_s_spec.rb b/spec/ruby/core/data/to_s_spec.rb
index 0b9099f035..2b4a670e8e 100644
--- a/spec/ruby/core/data/to_s_spec.rb
+++ b/spec/ruby/core/data/to_s_spec.rb
@@ -1,8 +1,6 @@
require_relative '../../spec_helper'
require_relative 'shared/inspect'
-ruby_version_is "3.2" do
- describe "Data#to_s" do
- it_behaves_like :data_inspect, :to_s
- end
+describe "Data#to_s" do
+ it_behaves_like :data_inspect, :to_s
end
diff --git a/spec/ruby/core/data/with_spec.rb b/spec/ruby/core/data/with_spec.rb
index 97e34c951f..fd0a99d1fa 100644
--- a/spec/ruby/core/data/with_spec.rb
+++ b/spec/ruby/core/data/with_spec.rb
@@ -1,35 +1,57 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data#with" do
- it "returns self if given no arguments" do
- data = DataSpecs::Measure.new(amount: 42, unit: "km")
- data = data.with.should.equal?(data)
- end
+describe "Data#with" do
+ it "returns self if given no arguments" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ data = data.with.should.equal?(data)
+ end
- it "accepts keyword arguments" do
- data = DataSpecs::Measure.new(amount: 42, unit: "km")
- data = data.with(amount: 4, unit: "m")
+ it "accepts keyword arguments" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ data = data.with(amount: 4, unit: "m")
- data.amount.should == 4
- data.unit.should == "m"
- end
+ data.amount.should == 4
+ data.unit.should == "m"
+ end
+
+ it "accepts String keyword arguments" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ data = data.with("amount" => 4, "unit" => "m")
+
+ data.amount.should == 4
+ data.unit.should == "m"
+ end
- it "accepts String keyword arguments" do
- data = DataSpecs::Measure.new(amount: 42, unit: "km")
- data = data.with("amount" => 4, "unit" => "m")
+ it "raises ArgumentError if no keyword arguments are given" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
- data.amount.should == 4
- data.unit.should == "m"
+ -> {
+ data.with(4, "m")
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 0)")
+ end
+
+ it "does not depend on the Data.new method" do
+ subclass = Class.new(DataSpecs::Measure)
+ data = subclass.new(amount: 42, unit: "km")
+
+ def subclass.new(*)
+ raise "Data.new is called"
end
- it "raises ArgumentError if no keyword arguments are given" do
- data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ data_copy = data.with(unit: "m")
+ data_copy.amount.should == 42
+ data_copy.unit.should == "m"
+ end
+
+ ruby_version_is "3.3" do
+ it "calls #initialize" do
+ data = DataSpecs::DataWithOverriddenInitialize.new(42, "m")
+ ScratchPad.clear
+
+ data.with(amount: 0)
- -> {
- data.with(4, "m")
- }.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 0)")
+ ScratchPad.recorded.should == [:initialize, [], {amount: 0, unit: "m"}]
end
end
end