1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
RSpec.describe Unparser::Concord do
let(:class_under_test) do
Class.new do
include Unparser::Concord.new(:foo, :bar)
end
end
let(:instance_a) { class_under_test.new(foo, bar) }
let(:instance_b) { class_under_test.new(foo, bar) }
let(:instance_c) { class_under_test.new(foo, double('Baz')) }
let(:foo) { double('Foo') }
let(:bar) { double('Bar') }
context 'initializer' do
it 'creates a private #initialize method' do
mod = Module.new
expect { mod.send(:include, Unparser::Concord.new) }
.to change { mod.private_method_defined?(:initialize) }
.from(false).to(true)
end
it 'does not cause warnings' do
begin
original = $stderr
$stderr = StringIO.new
Class.new do
include Unparser::Concord.new
end
expect($stderr.tap(&:rewind).read).to eql('')
ensure
$stderr = original
end
end
it 'creates an initializer that asserts the number of arguments' do
expect { class_under_test.new(1) }
.to raise_error(ArgumentError, 'wrong number of arguments (1 for 2)')
end
it 'creates an initializer that allows 2 arguments' do
expect { class_under_test.new(1, 2) }.to_not raise_error
end
it 'creates an initializer that is callable via super' do
class_under_test.class_eval do
attr_reader :baz
public :foo
public :bar
def initialize(foo, bar)
@baz = foo + bar
super(foo, bar)
end
end
instance = class_under_test.new(1, 2)
expect(instance.foo).to eql(1)
expect(instance.bar).to eql(2)
expect(instance.baz).to eql(3)
end
it 'creates an initializer that is callable via zsuper' do
class_under_test.class_eval do
attr_reader :baz
public :foo
public :bar
def initialize(foo, bar)
@baz = foo + bar
super
end
end
instance = class_under_test.new(1, 2)
expect(instance.foo).to eql(1)
expect(instance.bar).to eql(2)
expect(instance.baz).to eql(3)
end
it 'creates an initializer that sets the instance variables' do
instance = class_under_test.new(1, 2)
expect(instance.instance_variable_get(:@foo)).to be(1)
expect(instance.instance_variable_get(:@bar)).to be(2)
end
end
context 'with no objects to compose' do
it 'assigns no ivars' do
instance = Class.new { include Unparser::Concord.new }.new
expect(instance.instance_variables).to be_empty
end
end
context 'visibility' do
it 'should set attribute readers to protected' do
protected_methods = class_under_test.protected_instance_methods
expect(protected_methods).to match_array([:foo, :bar])
end
end
context 'attribute behavior' do
subject { instance_a }
specify { expect(subject.send(:foo)).to be(foo) }
specify { expect(subject.send(:bar)).to be(bar) }
end
context 'equalization behavior' do
specify 'composed objects are equalized on attributes' do
expect(instance_a).to eql(instance_b)
expect(instance_a.hash).to eql(instance_b.hash)
expect(instance_a).to eql(instance_b)
expect(instance_a).to_not be(instance_c)
expect(instance_a).to_not eql(instance_c)
end
end
context 'when composing too many objects' do
specify 'it raises an error' do
expect do
Unparser::Concord.new(:a, :b, :c, :d)
end.to raise_error(RuntimeError, 'Composition of more than 3 objects is not allowed')
expect do
Unparser::Concord.new(:a, :b, :c)
end.to_not raise_error
end
end
context Unparser::Concord::Public do
let(:class_under_test) do
Class.new do
include Unparser::Concord::Public.new(:foo, :bar)
end
end
it 'should create public attr readers' do
object = class_under_test.new(:foo, :bar)
expect(object.foo).to eql(:foo)
expect(object.bar).to eql(:bar)
end
end
end
|