redcrumbs 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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