File: value_object_spec.rb

package info (click to toggle)
ruby-virtus 2.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 660 kB
  • sloc: ruby: 4,378; makefile: 2
file content (138 lines) | stat: -rw-r--r-- 3,442 bytes parent folder | download | duplicates (3)
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
require 'spec_helper'

describe Virtus::ValueObject do
  shared_examples_for 'a valid value object' do
    subject { model.new(attributes) }

    let(:attributes) { Hash[:id => 1, :name => 'Jane Doe'] }

    describe '#id' do
      subject { super().id }
      it { is_expected.to be(1) }
    end

    describe '#name' do
      subject { super().name }
      it { is_expected.to eql('Jane Doe') }
    end

    it 'sets private writers' do
      expect(subject.class.attribute_set[:id]).to_not be_public_writer
      expect(subject.class.attribute_set[:name]).to_not be_public_writer
    end

    it 'disallows cloning' do
      expect(subject.clone).to be(subject)
    end

    it 'defines #eql?' do
      expect(subject).to eql(subject.class.new(attributes))
    end

    it 'defines #==' do
      expect(subject == subject.class.new(attributes)).to be(true)
    end

    it 'defines #hash' do
      expect(subject.hash).to eql(subject.class.new(attributes).hash)
    end

    it 'defines #inspect' do
      expect(subject.inspect).to eql(
        %(#<Model #{attributes.map { |k, v| "#{k}=#{v.inspect}" }.join(' ')}>)
      )
    end

    it 'allows to construct new values using #with' do
      new_instance = subject.with(:name => "John Doe")
      expect(new_instance.id).to eql(subject.id)
      expect(new_instance.name).to eql("John Doe")
    end
  end

  shared_examples_for 'a valid value object with mass-assignment turned on' do
    subject { model.new }

    it 'disallows mass-assignment' do
      expect(subject.private_methods).to include(:attributes=)
    end
  end

  context 'using new values {} block' do
    let(:model) {
      model = Virtus.value_object(:coerce => false, :mass_assignment => mass_assignment)

      Class.new {
        include model

        def self.name
          'Model'
        end

        values do
          attribute :id,   Integer
          attribute :name, String
        end
      }
    }

    context 'without mass-assignment' do
      let(:mass_assignment) { false }

      it_behaves_like 'a valid value object'
    end

    context 'with mass-assignment' do
      let(:mass_assignment) { true }

      it_behaves_like 'a valid value object'
      it_behaves_like 'a valid value object with mass-assignment turned on'

      context 'with a model subclass' do
        let(:subclass) {
          Class.new(model) {
            values do
              attribute :email, String
            end
          }
        }

        it_behaves_like 'a valid value object' do
          subject { subclass.new(attributes) }

          let(:attributes) { Hash[:id => 1, :name => 'Jane Doe', :email => 'jane@doe.com'] }

          describe '#email' do
            subject { super().email }
            it { is_expected.to eql('jane@doe.com') }
          end

          it 'sets private writers for additional values' do
            expect(subclass.attribute_set[:email]).to_not be_public_writer
          end

          it 'defines valid #== for a subclass' do
            expect(subject == subject.class.new(attributes.merge(:id => 2))).to be(false)
          end
        end
      end
    end
  end

  context 'using deprecated inclusion' do
    let(:model) {
      Class.new {
        include Virtus::ValueObject

        def self.name
          'Model'
        end

        attribute :id,   Integer
        attribute :name, String
      }
    }

    it_behaves_like 'a valid value object'
  end
end