redcrumbs 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,271 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Redcrumbs::Creation do
4
+ let(:name){ 'Paperboy' }
5
+ let(:score){ 12934 }
6
+
7
+ describe 'model' do
8
+ subject { Game.create(:name => name, :highscore => score) }
9
+
10
+ context 'when created' do
11
+ it { expect(subject.crumbs.count).to eq(1) }
12
+ end
13
+
14
+ context 'when single tracked attribute updated' do
15
+ it do
16
+ expect {
17
+ subject.update_attributes(:highscore => 12935)
18
+ }.to change { subject.crumbs.count }.by(1)
19
+ end
20
+ end
21
+
22
+ context 'when multiple tracked attributes updated' do
23
+ it do
24
+ expect {
25
+ subject.update_attributes(:highscore => 12935, :name => 'Paperboy 2')
26
+ }.to change { subject.crumbs.count }.by(1)
27
+ end
28
+ end
29
+
30
+ context 'when updated twice' do
31
+ it do
32
+ expect {
33
+ subject.update_attributes(:highscore => 12935)
34
+ subject.update_attributes(:name => 'Paperboy 2')
35
+ }.to change { subject.crumbs.count }.by(2)
36
+ end
37
+ end
38
+
39
+ context 'when untracked attribute updated' do
40
+ it do
41
+ expect {
42
+ subject.update_attributes(:platform => 'Commodore 64')
43
+ }.to change { subject.crumbs.count }.by(0)
44
+ end
45
+ end
46
+ end
47
+
48
+
49
+ describe 'conditional creation' do
50
+ before { @default_options = Game.redcrumbs_options.dup }
51
+ after { Game.redcrumbed(@default_options) }
52
+
53
+ context 'when `if` condition unsatisfied' do
54
+ before { Game.redcrumbed(:only => [:name], :if => :new_record?) }
55
+ subject { Game.new(name: name) }
56
+
57
+ it { expect { subject.save }.to change { subject.crumbs.count }.by(0) }
58
+ end
59
+
60
+ context 'when `unless` condition satisfied' do
61
+ before { Game.redcrumbed(:only => [:name], :unless => :persisted?) }
62
+ subject { Game.new(name: name) }
63
+
64
+ it { expect { subject.save }.to change { subject.crumbs.count }.by(0) }
65
+ end
66
+ end
67
+
68
+
69
+ describe "a created crumb's attributes" do
70
+ let(:computer_player) { ComputerPlayer.create(:name => 'Ramsey') }
71
+ let(:player) { Player.create(:name => 'Jon Hope') }
72
+
73
+ let(:game) { Game.create(:name => name, :highscore => score, :high_scorer => computer_player) }
74
+
75
+ before { game.update_attributes(:highscore => 15000, :platform => 'Amiga', :high_scorer => player) }
76
+
77
+ subject { game.crumbs.last }
78
+
79
+ it { is_expected.to have_attributes(:modifications => { 'highscore' => [12934, 15000] }) }
80
+ it { is_expected.to have_attributes(:subject_id => game.id) }
81
+ it { is_expected.to have_attributes(:subject_type => game.class.name) }
82
+ it { is_expected.to have_attributes(:creator_id => player.id) }
83
+ it { is_expected.to have_attributes(:creator_type => player.class.name) }
84
+ it { is_expected.to have_attributes(:target_id => computer_player.id) }
85
+ it { is_expected.to have_attributes(:target_type => computer_player.class.name) }
86
+ end
87
+
88
+
89
+ describe '.watched_changes' do
90
+ let(:game) { Game.create(:name => name, :highscore => score) }
91
+ subject { game.watched_changes }
92
+
93
+ context 'when changes made' do
94
+ before { game.assign_attributes(:name => 'Papergal', :platform => 'C64')}
95
+
96
+ it { is_expected.to include(:name) }
97
+ it { is_expected.not_to include(:platform) }
98
+ end
99
+
100
+ context 'when no changes made' do
101
+ it { is_expected.to eq({}) }
102
+ end
103
+ end
104
+
105
+
106
+ describe '.storable_attributes_keys' do
107
+ let!(:default_options) { Game.redcrumbs_options[:store].dup }
108
+ after { Game.redcrumbs_options[:store] = default_options}
109
+ subject { Game.new.storable_attributes_keys }
110
+
111
+ context 'when `only` set' do
112
+ before { Game.redcrumbs_options[:store] = {only: [:name]} }
113
+
114
+ it { is_expected.to eq([:name]) }
115
+ end
116
+
117
+ context 'when `except` set' do
118
+ before { Game.redcrumbs_options[:store] = {except: [:name]} }
119
+
120
+ it { is_expected.to include(:id, :created_at, :updated_at) }
121
+ it { is_expected.not_to include(:name) }
122
+ end
123
+
124
+ context 'when `only` and `except` set' do
125
+ before { Game.redcrumbs_options[:store] = {except: [:name], only: [:id]}}
126
+
127
+ it { is_expected.to eq([:id]) }
128
+ end
129
+
130
+ context 'when neither `only` or `except` set' do
131
+ before { Game.redcrumbs_options[:store] = {} }
132
+
133
+ it { is_expected.to eq([]) }
134
+ end
135
+ end
136
+
137
+
138
+ describe '.storeable_attributes' do
139
+ let!(:default_options) { Game.redcrumbs_options[:store].dup }
140
+ after { Game.redcrumbs_options[:store] = default_options}
141
+ subject { Game.new(name: name).storeable_attributes }
142
+
143
+ context 'when `only` set' do
144
+ before { Game.redcrumbs_options[:store] = {only: [:name]} }
145
+
146
+ it { is_expected.to eq({'name' => name}) }
147
+ end
148
+
149
+ context 'when `except` set' do
150
+ before { Game.redcrumbs_options[:store] = {except: [:name]} }
151
+
152
+ it { is_expected.to include('id', 'created_at', 'updated_at') }
153
+ it { is_expected.not_to include('name') }
154
+ end
155
+
156
+ context 'when `only` and `except` set' do
157
+ before { Game.redcrumbs_options[:store] = {except: [:name], only: [:id]}}
158
+
159
+ it { is_expected.to eq('id' => nil) }
160
+ end
161
+
162
+ context 'when neither `only` or `except` set' do
163
+ before { Game.redcrumbs_options[:store] = {} }
164
+
165
+ it { is_expected.to eq({}) }
166
+ end
167
+ end
168
+
169
+
170
+ describe '.storable_methods_names' do
171
+ let!(:default_options) { Game.redcrumbs_options[:store].dup }
172
+ after { Game.redcrumbs_options[:store] = default_options}
173
+ subject { Game.new.storable_methods_names }
174
+
175
+ context 'when `methods` set' do
176
+ before { Game.redcrumbs_options[:store] = {methods: [:persisted?]} }
177
+
178
+ it { is_expected.to eq([:persisted?]) }
179
+ end
180
+
181
+ context 'when `methods` not set' do
182
+ before { Game.redcrumbs_options[:store] = {} }
183
+
184
+ it { is_expected.to eq([]) }
185
+ end
186
+ end
187
+
188
+
189
+ describe '.storable_methods' do
190
+ let!(:default_options) { Game.redcrumbs_options[:store].dup }
191
+ after { Game.redcrumbs_options[:store] = default_options}
192
+ subject { Game.new.storable_methods }
193
+
194
+ context 'when `methods` set' do
195
+ before { Game.redcrumbs_options[:store] = {methods: [:persisted?]} }
196
+
197
+ it { is_expected.to include('persisted?') }
198
+ end
199
+
200
+ context 'when `methods` not set' do
201
+ before { Game.redcrumbs_options[:store] = {} }
202
+
203
+ it { is_expected.to eq({}) }
204
+ end
205
+ end
206
+
207
+
208
+ describe '.serialized_as_redcrumbs_subject' do
209
+ let!(:default_options) { Game.redcrumbs_options[:store].dup }
210
+ after { Game.redcrumbs_options[:store] = default_options}
211
+ subject { Game.new(name: name).serialized_as_redcrumbs_subject }
212
+
213
+ context 'when `store` set' do
214
+ before { Game.redcrumbs_options[:store] = {only: [:name]} }
215
+
216
+ it { is_expected.to eq({'name' => name}) }
217
+ end
218
+
219
+ context 'when `methods` set' do
220
+ before { Game.redcrumbs_options[:store] = {methods: [:persisted?]} }
221
+
222
+ it { is_expected.to eq({'persisted?' => false}) }
223
+ end
224
+
225
+ context 'when `store` and `methods` set' do
226
+ before { Game.redcrumbs_options[:store] = {only: [:name], methods: [:persisted?]} }
227
+
228
+ it { is_expected.to eq({'name' => name, 'persisted?' => false}) }
229
+ end
230
+
231
+ context 'when neither `store` or `methods` set' do
232
+ before { Game.redcrumbs_options[:store] = {} }
233
+
234
+ it { is_expected.to eq({}) }
235
+ end
236
+ end
237
+
238
+
239
+ describe '.create_crumb' do
240
+ let(:game) { Game.new(:name => name, :platform => 'C64') }
241
+ let(:crumb) { game.create_crumb }
242
+
243
+ context 'with created crumb' do
244
+ subject { crumb }
245
+ it { is_expected.to have_attributes(:subject => game)}
246
+ it { is_expected.to respond_to(:modifications)}
247
+ end
248
+
249
+ context 'with created crumb modifications' do
250
+ subject { crumb.modifications }
251
+
252
+ it { is_expected.to include(:name) }
253
+ it { is_expected.not_to include(:platform) }
254
+ end
255
+ end
256
+
257
+
258
+ describe '.notify_changes' do
259
+ let(:game) { Game.create(:name => name, :platform => 'C64') }
260
+
261
+ context 'without watched_changes' do
262
+ it { expect { game.notify_changes }.to change { game.crumbs.count }.by(0) }
263
+ end
264
+
265
+ context 'with watched_changes' do
266
+ before { game.name = 'Paperperson' }
267
+
268
+ it { expect { game.notify_changes }.to change { game.crumbs.count }.by(1) }
269
+ end
270
+ end
271
+ end
@@ -0,0 +1,254 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Redcrumbs::Crumb do
4
+ let(:player) { Player.create(:name => 'Jon Hope') }
5
+ let(:player_2) { Player.create(:name => 'Ash Dwyer') }
6
+ let(:game) { Game.create(:name => 'Paperboy', :highscore => 4001) }
7
+
8
+ describe 'self.build_with_modifications' do
9
+ context 'when subject has no changes' do
10
+ subject { Redcrumbs::Crumb.build_with_modifications(game) }
11
+
12
+ it { is_expected.to be_nil }
13
+ end
14
+
15
+ context 'when subject has no watched changes' do
16
+ before { game.platform = 'Spectrum'}
17
+ subject { Redcrumbs::Crumb.build_with_modifications(game) }
18
+
19
+ it { is_expected.to be_nil }
20
+ end
21
+
22
+ context 'when subject has changes' do
23
+ before { game.assign_attributes(:highscore => 19000, :name => 'Papergal') }
24
+
25
+ subject { Redcrumbs::Crumb.build_with_modifications(game).modifications }
26
+
27
+ it { is_expected.not_to eq({}) }
28
+ it { is_expected.to include('highscore' => [4001, 19000]) }
29
+ it { is_expected.to include('name' => ['Paperboy', 'Papergal']) }
30
+ end
31
+ end
32
+
33
+
34
+ describe 'subject' do
35
+ let(:crumb) { game.crumbs.last }
36
+
37
+ context 'when instantiating a stored subject' do
38
+ subject! { crumb.subject }
39
+
40
+ it { is_expected.to be_present }
41
+ it { expect(subject.id).to eq(game.id) }
42
+ it { expect(subject.name).to eq(game.name) }
43
+ it { expect(subject.highscore).to be_nil }
44
+ it { expect(crumb).not_to have_loaded_subject }
45
+ end
46
+
47
+ context 'when retrieving a full subject' do
48
+ subject! { crumb.full_subject }
49
+
50
+ it { is_expected.to be_present }
51
+ it { is_expected.to eq(game) }
52
+ it { expect(subject.highscore).to eq(game.highscore) }
53
+ it { expect(crumb).to have_loaded_subject }
54
+ end
55
+ end
56
+
57
+
58
+ describe 'creator' do
59
+ let!(:default_options) { Redcrumbs.store_creator_attributes.dup }
60
+ let(:crumb) { game.crumbs.last }
61
+
62
+ before do
63
+ Redcrumbs.store_creator_attributes = [:name]
64
+ game.update_attributes(:highscore => 20000, :high_scorer => player)
65
+ end
66
+
67
+ after { Redcrumbs.store_creator_attributes = default_options }
68
+
69
+ context 'when nil' do
70
+ subject(:creator) { game.crumbs.first.creator }
71
+
72
+ it { is_expected.not_to be_present }
73
+ end
74
+
75
+ context 'when instantiating from storage' do
76
+ subject!(:creator) { crumb.creator }
77
+
78
+ it { is_expected.to be_present }
79
+ it { expect(creator.id).to eq(player.id) }
80
+ it { expect(creator.name).to eq(player.name) }
81
+ it { expect(creator.created_at).to be_nil }
82
+ it { expect(crumb).not_to have_loaded_creator }
83
+ end
84
+
85
+ context 'when retrieving a full creator' do
86
+ subject!(:creator) { crumb.full_creator }
87
+
88
+ it { is_expected.to be_present }
89
+ it { is_expected.to eq(player) }
90
+ it { expect(creator.created_at.to_i).to eq(player.created_at.to_i) }
91
+ it { expect(crumb).to have_loaded_creator }
92
+ end
93
+ end
94
+
95
+
96
+ describe 'target' do
97
+ let!(:default_options) { Redcrumbs.store_target_attributes.dup }
98
+ let(:crumb) { game.crumbs.last }
99
+
100
+ before do
101
+ Redcrumbs.store_target_attributes = [:name]
102
+ game.update_attributes(:highscore => 19890, :high_scorer => player)
103
+ game.update_attributes(:highscore => 20000, :high_scorer => player_2)
104
+ end
105
+
106
+ after { Redcrumbs.store_target_attributes = default_options }
107
+
108
+ context 'when nil' do
109
+ subject(:target) { game.crumbs.first.target }
110
+
111
+ it { is_expected.not_to be_present }
112
+ end
113
+
114
+ context 'when instantiating from storage' do
115
+ subject!(:target) { crumb.target }
116
+
117
+ it { is_expected.to be_present }
118
+ it { expect(target.id).to eq(player.id) }
119
+ it { expect(target.name).to eq(player.name) }
120
+ it { expect(target.created_at).to be_nil }
121
+ it { expect(crumb).not_to have_loaded_target }
122
+ end
123
+
124
+ context 'when retrieving a full target' do
125
+ subject!(:target) { crumb.full_target }
126
+
127
+ it { is_expected.to be_present }
128
+ it { is_expected.to eq(player) }
129
+ it { expect(target.created_at.to_i).to eq(player.created_at.to_i) }
130
+ it { expect(crumb).to have_loaded_target }
131
+ end
132
+ end
133
+
134
+
135
+ describe 'self.initialize' do
136
+ context 'with modifications' do
137
+ subject { Redcrumbs::Crumb.new(modifications: {'name' => [nil, 'Paperboy']}).modifications }
138
+
139
+ it { is_expected.not_to eq({}) }
140
+ it { is_expected.to include('name' => [nil, 'Paperboy']) }
141
+ end
142
+
143
+ context 'with subject' do
144
+ subject { Redcrumbs::Crumb.new(subject: game) }
145
+
146
+ it { is_expected.to have_attributes(:subject => game) }
147
+ it { is_expected.to have_attributes(:subject_id => game.id) }
148
+ it { is_expected.to have_attributes(:subject_type => game.class.name) }
149
+ end
150
+ end
151
+
152
+
153
+ describe '.redis_key' do
154
+ let!(:crumb) { Redcrumbs::Crumb.new(subject: game) }
155
+
156
+ context 'when new' do
157
+ subject { crumb.redis_key }
158
+
159
+ it { is_expected.to be_nil }
160
+ end
161
+
162
+ context 'when persisted' do
163
+ before { crumb.save }
164
+ subject { crumb.redis_key }
165
+
166
+ it { is_expected.to eq("redcrumbs_crumbs:#{crumb.id}")}
167
+ end
168
+ end
169
+
170
+
171
+ describe '.mortal?' do
172
+ let!(:default_value) { Redcrumbs.mortality }
173
+
174
+ context 'when unpersisted' do
175
+ subject { Redcrumbs::Crumb.new(subject: game).mortal? }
176
+
177
+ it { is_expected.to be_falsey }
178
+ end
179
+
180
+ context 'when mortal' do
181
+ before { Redcrumbs.mortality = 30.days }
182
+ after { Redcrumbs.mortality = default_value }
183
+ subject { Redcrumbs::Crumb.create(subject: game).mortal? }
184
+
185
+ it { is_expected.to be_truthy }
186
+ end
187
+
188
+ context 'when immortal' do
189
+ before { Redcrumbs.mortality = nil }
190
+ after { Redcrumbs.mortality = default_value }
191
+ subject { Redcrumbs::Crumb.create.mortal? }
192
+
193
+ it { is_expected.to be_falsey }
194
+ end
195
+ end
196
+
197
+
198
+ describe '.time_to_live' do
199
+ let!(:default_value) { Redcrumbs.mortality }
200
+
201
+ context 'when unpersisted' do
202
+ subject { Redcrumbs::Crumb.new(subject: game).time_to_live }
203
+
204
+ it { is_expected.to be_nil }
205
+ end
206
+
207
+ context 'when immortal' do
208
+ before { Redcrumbs.mortality = nil }
209
+ after { Redcrumbs.mortality = default_value }
210
+ subject { Redcrumbs::Crumb.create(subject: game).time_to_live }
211
+
212
+ it { is_expected.to eq(-1) }
213
+ end
214
+
215
+ context 'when mortal' do
216
+ before { Redcrumbs.mortality = 30.days }
217
+ after { Redcrumbs.mortality = default_value }
218
+ subject { Redcrumbs::Crumb.create(subject: game) }
219
+
220
+ it { expect(subject.time_to_live).to be_truthy }
221
+ it { expect(subject.time_to_live).to be_within(2.seconds.to_i).of(30.days.to_i) }
222
+ end
223
+ end
224
+
225
+
226
+ describe '.expires_at' do
227
+ let!(:default_value) { Redcrumbs.mortality }
228
+
229
+ context 'when unpersisted' do
230
+ let(:crumb) { Redcrumbs::Crumb.new }
231
+ subject { crumb.expires_at }
232
+
233
+ it { is_expected.to be_nil }
234
+ end
235
+
236
+ context 'when mortal' do
237
+ before { Redcrumbs.mortality = 30.days }
238
+ after { Redcrumbs.mortality = default_value }
239
+ let(:crumb) { Redcrumbs::Crumb.create }
240
+ subject { crumb.expires_at.to_i }
241
+
242
+ it { is_expected.to be_truthy }
243
+ it { is_expected.to eq((Time.now + crumb.time_to_live).to_i) }
244
+ end
245
+
246
+ context 'when immortal' do
247
+ before { Redcrumbs.mortality = nil }
248
+ after { Redcrumbs.mortality = default_value }
249
+ subject { Redcrumbs::Crumb.new.expires_at }
250
+
251
+ it { is_expected.to be_nil }
252
+ end
253
+ end
254
+ end