draftsman 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +3 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +97 -0
- data/LICENSE +20 -0
- data/README.md +506 -0
- data/Rakefile +6 -0
- data/draftsman.gemspec +33 -0
- data/lib/draftsman/config.rb +13 -0
- data/lib/draftsman/draft.rb +289 -0
- data/lib/draftsman/frameworks/cucumber.rb +7 -0
- data/lib/draftsman/frameworks/rails.rb +58 -0
- data/lib/draftsman/frameworks/rspec.rb +16 -0
- data/lib/draftsman/frameworks/sinatra.rb +31 -0
- data/lib/draftsman/model.rb +428 -0
- data/lib/draftsman/serializers/json.rb +17 -0
- data/lib/draftsman/serializers/yaml.rb +17 -0
- data/lib/draftsman/version.rb +3 -0
- data/lib/draftsman.rb +101 -0
- data/lib/generators/draftsman/install_generator.rb +27 -0
- data/lib/generators/draftsman/templates/add_object_changes_column_to_drafts.rb +9 -0
- data/lib/generators/draftsman/templates/config/initializers/draftsman.rb +11 -0
- data/lib/generators/draftsman/templates/create_drafts.rb +22 -0
- data/spec/controllers/informants_controller_spec.rb +27 -0
- data/spec/controllers/users_controller_spec.rb +23 -0
- data/spec/controllers/whodunnits_controller_spec.rb +24 -0
- data/spec/draftsman_spec.rb +19 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/images/rails.png +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +20 -0
- data/spec/dummy/app/controllers/informants_controller.rb +8 -0
- data/spec/dummy/app/controllers/users_controller.rb +8 -0
- data/spec/dummy/app/controllers/whodunnits_controller.rb +8 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/helpers/messages_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/bastard.rb +3 -0
- data/spec/dummy/app/models/child.rb +4 -0
- data/spec/dummy/app/models/parent.rb +5 -0
- data/spec/dummy/app/models/trashable.rb +3 -0
- data/spec/dummy/app/models/vanilla.rb +3 -0
- data/spec/dummy/app/models/whitelister.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +15 -0
- data/spec/dummy/config/application.rb +37 -0
- data/spec/dummy/config/boot.rb +6 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +32 -0
- data/spec/dummy/config/environments/production.rb +73 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +6 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20110208155312_set_up_test_tables.rb +86 -0
- data/spec/dummy/db/schema.rb +106 -0
- data/spec/dummy/db/seeds.rb +7 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/lib/tasks/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/models/child_spec.rb +205 -0
- data/spec/models/draft_spec.rb +297 -0
- data/spec/models/parent_spec.rb +191 -0
- data/spec/models/trashable_spec.rb +164 -0
- data/spec/models/vanilla_spec.rb +201 -0
- data/spec/models/whitelister_spec.rb +262 -0
- data/spec/spec_helper.rb +52 -0
- metadata +304 -0
@@ -0,0 +1,297 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Draftsman::Draft do
|
4
|
+
let(:trashable) { Trashable.new :name => 'Bob' }
|
5
|
+
subject { trashable.draft }
|
6
|
+
|
7
|
+
describe :event, :create?, :update?, :destroy?, :object, :changeset do
|
8
|
+
context 'with `create` draft' do
|
9
|
+
before { trashable.draft_creation }
|
10
|
+
its(:event) { should eql 'create' }
|
11
|
+
its(:create?) { should be_true }
|
12
|
+
its(:update?) { should be_false }
|
13
|
+
its(:destroy?) { should be_false }
|
14
|
+
its(:object) { should be_present }
|
15
|
+
its(:changeset) { should include :id }
|
16
|
+
its(:changeset) { should include :name }
|
17
|
+
its(:changeset) { should_not include :title }
|
18
|
+
its(:changeset) { should include :created_at }
|
19
|
+
its(:changeset) { should include :updated_at }
|
20
|
+
its(:previous_draft) { should be_nil }
|
21
|
+
|
22
|
+
context 'updated create' do
|
23
|
+
before do
|
24
|
+
trashable.name = 'Sam'
|
25
|
+
trashable.draft_update
|
26
|
+
end
|
27
|
+
|
28
|
+
it { should be_create }
|
29
|
+
it { should_not be_update }
|
30
|
+
it { should_not be_destroy }
|
31
|
+
its(:event) { should eql 'create' }
|
32
|
+
its(:object) { should be_present }
|
33
|
+
its(:changeset) { should include :id }
|
34
|
+
its(:changeset) { should include :name }
|
35
|
+
its(:changeset) { should_not include :title }
|
36
|
+
its(:changeset) { should include :created_at }
|
37
|
+
its(:changeset) { should include :updated_at }
|
38
|
+
its(:previous_draft) { should be_nil }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'with `update` draft' do
|
43
|
+
before do
|
44
|
+
trashable.save!
|
45
|
+
trashable.name = 'Sam'
|
46
|
+
trashable.title = 'My Title'
|
47
|
+
trashable.draft_update
|
48
|
+
end
|
49
|
+
|
50
|
+
it { should_not be_create }
|
51
|
+
it { should be_update }
|
52
|
+
it { should_not be_destroy }
|
53
|
+
its(:event) { should eql 'update' }
|
54
|
+
its(:object) { should be_present }
|
55
|
+
its(:changeset) { should_not include :id }
|
56
|
+
its(:changeset) { should include :name }
|
57
|
+
its(:changeset) { should include :title }
|
58
|
+
its(:changeset) { should_not include :created_at }
|
59
|
+
its(:changeset) { should_not include :updated_at }
|
60
|
+
its(:previous_draft) { should be_nil }
|
61
|
+
|
62
|
+
context 'updating the update' do
|
63
|
+
before do
|
64
|
+
trashable.title = nil
|
65
|
+
trashable.draft_update
|
66
|
+
end
|
67
|
+
|
68
|
+
it { should_not be_create }
|
69
|
+
it { should be_update }
|
70
|
+
it { should_not be_destroy }
|
71
|
+
its(:event) { should eql 'update' }
|
72
|
+
its(:object) { should be_present }
|
73
|
+
its(:changeset) { should_not include :id }
|
74
|
+
its(:changeset) { should include :name }
|
75
|
+
its(:changeset) { should_not include :title }
|
76
|
+
its(:changeset) { should_not include :created_at }
|
77
|
+
its(:changeset) { should_not include :updated_at }
|
78
|
+
its(:previous_draft) { should be_nil }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'with `destroy` draft' do
|
83
|
+
context 'without previous draft' do
|
84
|
+
before do
|
85
|
+
trashable.save!
|
86
|
+
trashable.draft_destroy
|
87
|
+
end
|
88
|
+
|
89
|
+
it { should_not be_create }
|
90
|
+
it { should_not be_update }
|
91
|
+
it { should be_destroy }
|
92
|
+
it { should_not be_destroyed }
|
93
|
+
its(:event) { should eql 'destroy' }
|
94
|
+
its(:object) { should be_present }
|
95
|
+
its(:changeset) { should eql Hash.new }
|
96
|
+
its(:previous_draft) { should be_nil }
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'with previous `create` draft' do
|
100
|
+
before do
|
101
|
+
trashable.draft_creation
|
102
|
+
trashable.draft_destroy
|
103
|
+
end
|
104
|
+
|
105
|
+
it { should_not be_create }
|
106
|
+
it { should_not be_update }
|
107
|
+
it { should be_destroy }
|
108
|
+
it { should_not be_destroyed }
|
109
|
+
its(:event) { should eql 'destroy' }
|
110
|
+
its(:object) { should be_present }
|
111
|
+
its(:changeset) { should include :id }
|
112
|
+
its(:changeset) { should include :name }
|
113
|
+
its(:changeset) { should_not include :title }
|
114
|
+
its(:changeset) { should include :created_at }
|
115
|
+
its(:changeset) { should include :updated_at }
|
116
|
+
its(:previous_draft) { should be_present }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe :publish! do
|
122
|
+
context 'with `create` draft' do
|
123
|
+
before { trashable.draft_creation }
|
124
|
+
subject { trashable.draft.publish!; return trashable.reload }
|
125
|
+
it { expect { subject }.to_not raise_exception }
|
126
|
+
it { should be_published }
|
127
|
+
it { should_not be_trashed }
|
128
|
+
it { should_not be_draft }
|
129
|
+
its(:published_at) { should be_present }
|
130
|
+
its(:draft_id) { should be_nil }
|
131
|
+
its(:draft) { should be_nil }
|
132
|
+
its(:trashed_at) { should be_nil }
|
133
|
+
|
134
|
+
it 'deletes the draft' do
|
135
|
+
expect { subject }.to change(Draftsman::Draft, :count).by(-1)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context 'with `update` draft' do
|
140
|
+
before do
|
141
|
+
trashable.save!
|
142
|
+
trashable.name = 'Sam'
|
143
|
+
trashable.draft_update
|
144
|
+
end
|
145
|
+
|
146
|
+
subject { trashable.draft.publish!; return trashable.reload }
|
147
|
+
it { expect { subject }.to_not raise_exception }
|
148
|
+
it { should be_published }
|
149
|
+
it { should_not be_draft }
|
150
|
+
it { should_not be_trashed }
|
151
|
+
its(:name) { should eql 'Sam' }
|
152
|
+
its(:published_at) { should be_present }
|
153
|
+
its(:draft_id) { should be_nil }
|
154
|
+
its(:draft) { should be_nil }
|
155
|
+
its(:trashed_at) { should be_nil }
|
156
|
+
|
157
|
+
it 'deletes the draft' do
|
158
|
+
expect { subject }.to change(Draftsman::Draft, :count).by(-1)
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'does not delete the associated item' do
|
162
|
+
expect { subject }.to_not change(Trashable, :count)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context 'with `destroy` draft' do
|
167
|
+
context 'without previous draft' do
|
168
|
+
before do
|
169
|
+
trashable.save!
|
170
|
+
trashable.draft_destroy
|
171
|
+
end
|
172
|
+
|
173
|
+
subject { trashable.draft.publish! }
|
174
|
+
|
175
|
+
it 'destroys the draft' do
|
176
|
+
expect { subject }.to change(Draftsman::Draft, :count).by(-1)
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'deletes the associated item' do
|
180
|
+
expect { subject }.to change(Trashable, :count).by(-1)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context 'with previous `create` draft' do
|
185
|
+
before do
|
186
|
+
trashable.draft_creation
|
187
|
+
trashable.draft_destroy
|
188
|
+
end
|
189
|
+
|
190
|
+
subject { trashable.draft.publish! }
|
191
|
+
|
192
|
+
it 'destroys the draft' do
|
193
|
+
expect { subject }.to change(Draftsman::Draft, :count).by(-1)
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'deletes the associated item' do
|
197
|
+
expect { subject }.to change(Trashable, :count).by(-1)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe :revert! do
|
204
|
+
context 'with `create` draft' do
|
205
|
+
before { trashable.draft_creation }
|
206
|
+
subject { trashable.draft.revert! }
|
207
|
+
it { expect { subject }.to_not raise_exception }
|
208
|
+
|
209
|
+
it 'deletes the draft' do
|
210
|
+
expect { subject }.to change(Draftsman::Draft, :count).by(-1)
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'deletes associated item' do
|
214
|
+
expect { subject }.to change(Trashable, :count).by(-1)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
context 'with `update` draft' do
|
219
|
+
before do
|
220
|
+
trashable.save!
|
221
|
+
trashable.name = 'Sam'
|
222
|
+
trashable.draft_update
|
223
|
+
end
|
224
|
+
|
225
|
+
subject { trashable.draft.revert!; return trashable.reload }
|
226
|
+
it { expect { subject }.to_not raise_exception }
|
227
|
+
it { should_not be_draft }
|
228
|
+
its(:name) { should eql 'Bob' }
|
229
|
+
its(:draft_id) { should be_nil }
|
230
|
+
its(:draft) { should be_nil }
|
231
|
+
|
232
|
+
it 'deletes the draft' do
|
233
|
+
expect { subject }.to change(Draftsman::Draft, :count).by(-1)
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'does not delete the associated item' do
|
237
|
+
expect { subject }.to_not change(Trashable, :count)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
context 'with `destroy` draft' do
|
242
|
+
context 'without previous draft' do
|
243
|
+
before do
|
244
|
+
trashable.save!
|
245
|
+
trashable.draft_destroy
|
246
|
+
end
|
247
|
+
|
248
|
+
subject { trashable.draft.revert!; return trashable.reload }
|
249
|
+
it { expect { subject }.to_not raise_exception }
|
250
|
+
it { should_not be_trashed }
|
251
|
+
it { should_not be_draft }
|
252
|
+
its(:draft_id) { should be_nil }
|
253
|
+
its(:draft) { should be_nil }
|
254
|
+
its(:trashed_at) { should be_nil }
|
255
|
+
|
256
|
+
it 'deletes the draft' do
|
257
|
+
expect { subject }.to change(Draftsman::Draft, :count).by(-1)
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'does not delete the associated item' do
|
261
|
+
expect { subject }.to_not change(Trashable, :count)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
context 'with previous `create` draft' do
|
266
|
+
before do
|
267
|
+
trashable.draft_creation
|
268
|
+
trashable.draft_destroy
|
269
|
+
end
|
270
|
+
|
271
|
+
subject { trashable.draft.revert!; return trashable.reload }
|
272
|
+
it { expect { subject }.to_not raise_exception }
|
273
|
+
it { should_not be_trashed }
|
274
|
+
it { should be_draft }
|
275
|
+
its(:draft_id) { should be_present }
|
276
|
+
its(:draft) { should be_present }
|
277
|
+
its(:trashed_at) { should be_nil }
|
278
|
+
|
279
|
+
it 'deletes the `destroy` draft' do
|
280
|
+
expect { subject }.to change(Draftsman::Draft.where(:event => 'destroy'), :count).by(-1)
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'reifies the previous `create` draft' do
|
284
|
+
expect { subject }.to change(Draftsman::Draft.where(:event => 'create'), :count).by(1)
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'does not delete the associated item' do
|
288
|
+
expect { subject }.to_not change(Trashable, :count)
|
289
|
+
end
|
290
|
+
|
291
|
+
its "draft's previous draft should be nil" do
|
292
|
+
subject.draft.previous_draft.should be_nil
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Parent do
|
4
|
+
let(:parent) { Parent.new(:name => 'Marge') }
|
5
|
+
let(:child) { Child.new(:name => 'Lisa', :parent => parent) }
|
6
|
+
|
7
|
+
describe :publish! do
|
8
|
+
context 'parent `create` draft with child `create` draft' do
|
9
|
+
before do
|
10
|
+
parent.draft_creation
|
11
|
+
child.draft_creation
|
12
|
+
end
|
13
|
+
|
14
|
+
subject { parent.draft.publish! }
|
15
|
+
|
16
|
+
its 'parent should be published' do
|
17
|
+
subject
|
18
|
+
parent.reload.should be_published
|
19
|
+
end
|
20
|
+
|
21
|
+
its 'parent should not be a draft' do
|
22
|
+
subject
|
23
|
+
parent.reload.should_not be_draft
|
24
|
+
end
|
25
|
+
|
26
|
+
its 'child should be a draft' do
|
27
|
+
subject
|
28
|
+
child.reload.should be_draft
|
29
|
+
end
|
30
|
+
|
31
|
+
its 'child should not be published' do
|
32
|
+
subject
|
33
|
+
child.reload.should_not be_published
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'destroys 1 draft' do
|
37
|
+
expect { subject }.to change(Draftsman::Draft, :count).by(-1)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "destroys the parent's draft" do
|
41
|
+
expect { subject }.to change(Draftsman::Draft.where(:item_type => 'Parent'), :count).by(-1)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'parent `destroy` draft with child `destroy` draft' do
|
46
|
+
before do
|
47
|
+
child.save!
|
48
|
+
child.draft_destroy
|
49
|
+
parent.draft_destroy
|
50
|
+
end
|
51
|
+
|
52
|
+
subject { parent.draft.publish! }
|
53
|
+
|
54
|
+
it 'destroys the parent' do
|
55
|
+
expect { subject }.to change(Parent, :count).by(-1)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'destroys the child' do
|
59
|
+
expect { subject }.to change(Child, :count).by(-1)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'destroys 2 drafts' do
|
63
|
+
expect { subject }.to change(Draftsman::Draft, :count).by(-2)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe :revert! do
|
69
|
+
context 'parent `create` draft with child `create` draft' do
|
70
|
+
before do
|
71
|
+
parent.draft_creation
|
72
|
+
child.draft_creation
|
73
|
+
end
|
74
|
+
|
75
|
+
subject { parent.draft.revert! }
|
76
|
+
|
77
|
+
it 'destroys the parent' do
|
78
|
+
expect { subject }.to change(Parent, :count).by(-1)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'destroys the child' do
|
82
|
+
expect { subject }.to change(Child, :count).by(-1)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'destroys both drafts' do
|
86
|
+
expect { subject }.to change(Draftsman::Draft, :count).by(-2)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'parent `destroy` draft with child `destroy` draft' do
|
91
|
+
before do
|
92
|
+
child.save!
|
93
|
+
child.draft_destroy
|
94
|
+
parent.draft_destroy
|
95
|
+
end
|
96
|
+
|
97
|
+
subject do
|
98
|
+
parent.draft.revert!
|
99
|
+
child.reload
|
100
|
+
parent.reload
|
101
|
+
end
|
102
|
+
|
103
|
+
it { should be_persisted }
|
104
|
+
it { should_not be_draft }
|
105
|
+
it { should_not be_trashed }
|
106
|
+
|
107
|
+
it "keeps the child's draft" do
|
108
|
+
expect { subject }.to_not change(Draftsman::Draft.where(:item_type => 'Child'), :count)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "deletes the parent's draft" do
|
112
|
+
expect { subject }.to change(Draftsman::Draft.where(:item_type => 'Parent'), :count).by(-1)
|
113
|
+
end
|
114
|
+
|
115
|
+
its 'child should remain a draft' do
|
116
|
+
subject
|
117
|
+
child.should be_draft
|
118
|
+
end
|
119
|
+
|
120
|
+
its 'child should still be a `destroy` draft' do
|
121
|
+
subject
|
122
|
+
child.draft.reload.should be_destroy
|
123
|
+
end
|
124
|
+
|
125
|
+
its 'child should still be trashed' do
|
126
|
+
subject
|
127
|
+
child.should be_trashed
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe :draft_publication_dependencies do
|
133
|
+
context 'parent `create` draft with child `create` draft' do
|
134
|
+
before do
|
135
|
+
parent.draft_creation
|
136
|
+
child.draft_creation
|
137
|
+
end
|
138
|
+
|
139
|
+
subject { parent.draft }
|
140
|
+
its(:draft_publication_dependencies) { should be_empty }
|
141
|
+
end
|
142
|
+
|
143
|
+
context 'parent `update` draft with child `create` draft' do
|
144
|
+
before do
|
145
|
+
parent.save!
|
146
|
+
parent.name = 'Selma'
|
147
|
+
parent.draft_update
|
148
|
+
child.draft_creation
|
149
|
+
end
|
150
|
+
|
151
|
+
subject { parent.draft }
|
152
|
+
its(:draft_publication_dependencies) { should be_empty }
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'parent `destroy` draft with child `destroy` draft' do
|
156
|
+
before do
|
157
|
+
child.save!
|
158
|
+
parent.draft_destroy
|
159
|
+
child.reload
|
160
|
+
end
|
161
|
+
|
162
|
+
subject { parent.draft }
|
163
|
+
its(:draft_publication_dependencies) { should be_present }
|
164
|
+
its(:draft_publication_dependencies) { should include child.draft }
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe :draft_reversion_dependencies do
|
169
|
+
context 'parent `create` draft with child `create` draft' do
|
170
|
+
before do
|
171
|
+
parent.draft_creation
|
172
|
+
child.draft_creation
|
173
|
+
end
|
174
|
+
|
175
|
+
subject { parent.draft }
|
176
|
+
its(:draft_reversion_dependencies) { should be_present }
|
177
|
+
its(:draft_reversion_dependencies) { should include child.draft }
|
178
|
+
end
|
179
|
+
|
180
|
+
context 'parent `destroy` draft with child `destroy` draft' do
|
181
|
+
before do
|
182
|
+
child.save!
|
183
|
+
parent.draft_destroy
|
184
|
+
child.reload
|
185
|
+
end
|
186
|
+
|
187
|
+
subject { parent.draft }
|
188
|
+
its(:draft_reversion_dependencies) { should be_empty }
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# A Trashable has a simple call to `has_drafts` without any options specified. The model also contains a `deleted_at`
|
4
|
+
# attribute, which allows deletes to be drafts too.
|
5
|
+
describe Trashable do
|
6
|
+
let(:trashable) { Trashable.new :name => 'Bob' }
|
7
|
+
it { should be_draftable }
|
8
|
+
|
9
|
+
# Not affected by this customization
|
10
|
+
describe :draft_creation do
|
11
|
+
end
|
12
|
+
|
13
|
+
# Not affected by this customization
|
14
|
+
describe :draft_update do
|
15
|
+
end
|
16
|
+
|
17
|
+
describe :draft_destroy do
|
18
|
+
context 'with `:create` draft' do
|
19
|
+
before { trashable.draft_creation }
|
20
|
+
subject { trashable.draft_destroy; return trashable }
|
21
|
+
it { should be_persisted }
|
22
|
+
it { should_not be_published }
|
23
|
+
it { should be_draft }
|
24
|
+
it { should be_trashed}
|
25
|
+
its(:published_at) { should be_nil }
|
26
|
+
its(:trashed_at) { should be_present }
|
27
|
+
its(:draft_id) { should be_present }
|
28
|
+
its(:draft) { should be_present }
|
29
|
+
its(:draft) { should be_destroy }
|
30
|
+
its(:name) { should eql 'Bob' }
|
31
|
+
|
32
|
+
it 'keeps the item' do
|
33
|
+
expect { subject }.to_not change(Trashable, :count)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'keeps the associated draft' do
|
37
|
+
expect { subject }.to_not change(Draftsman::Draft.where(:id => trashable.draft_id), :count)
|
38
|
+
end
|
39
|
+
|
40
|
+
its "draft's name should be 'Bob'" do
|
41
|
+
subject.draft.reify.name.should eql 'Bob'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'with `:update` draft' do
|
46
|
+
before do
|
47
|
+
trashable.save!
|
48
|
+
trashable.published_at = Time.now
|
49
|
+
trashable.save!
|
50
|
+
trashable.name = 'Sam'
|
51
|
+
trashable.draft_update
|
52
|
+
end
|
53
|
+
|
54
|
+
subject { trashable.draft_destroy; return trashable.reload }
|
55
|
+
it { should be_persisted }
|
56
|
+
it { should be_published }
|
57
|
+
it { should be_draft }
|
58
|
+
it { should be_trashed}
|
59
|
+
its(:published_at) { should be_present }
|
60
|
+
its(:trashed_at) { should be_present }
|
61
|
+
its(:draft_id) { should be_present }
|
62
|
+
its(:draft) { should be_present }
|
63
|
+
its(:draft) { should be_destroy }
|
64
|
+
its(:name) { should eql 'Bob' }
|
65
|
+
|
66
|
+
it 'keeps the item' do
|
67
|
+
expect { subject }.to_not change(Trashable, :count)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'keeps the associated draft' do
|
71
|
+
expect { subject }.to_not change(Draftsman::Draft.where(:id => trashable.draft_id), :count)
|
72
|
+
end
|
73
|
+
|
74
|
+
its "draft's name should be 'Sam'" do
|
75
|
+
subject.draft.reify.name.should eql 'Sam'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'without draft' do
|
80
|
+
before do
|
81
|
+
trashable.save!
|
82
|
+
trashable.update_attributes! :published_at => Time.now
|
83
|
+
end
|
84
|
+
|
85
|
+
subject { trashable.draft_destroy; return trashable.reload }
|
86
|
+
it { should be_persisted }
|
87
|
+
it { should be_published }
|
88
|
+
it { should be_draft }
|
89
|
+
it { should be_trashed }
|
90
|
+
its(:published_at) { should be_present }
|
91
|
+
its(:trashed_at) { should be_present }
|
92
|
+
its(:draft_id) { should be_present }
|
93
|
+
its(:draft) { should be_present }
|
94
|
+
its(:draft) { should be_destroy }
|
95
|
+
its(:name) { should eql 'Bob' }
|
96
|
+
|
97
|
+
it 'keeps the item' do
|
98
|
+
expect { subject }.to_not change(Trashable, :count)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'creates a draft' do
|
102
|
+
expect { subject }.to change(Draftsman::Draft, :count).by(1)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'scopes' do
|
108
|
+
let!(:drafted_trashable) { trashable.draft_creation; return trashable }
|
109
|
+
let!(:published_trashable) { Trashable.create :name => 'Jane', :published_at => Time.now }
|
110
|
+
let!(:trashed_trashable) { Trashable.create :name => 'Ralph' }
|
111
|
+
|
112
|
+
# Not affected by this customization
|
113
|
+
describe :drafted do
|
114
|
+
end
|
115
|
+
|
116
|
+
describe :live do
|
117
|
+
before { trashed_trashable.draft_destroy }
|
118
|
+
subject { Trashable.live }
|
119
|
+
its(:count) { should eql 2 }
|
120
|
+
|
121
|
+
it 'does not raise an exception' do
|
122
|
+
expect { subject }.to_not raise_exception
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'includes the drafted item' do
|
126
|
+
subject.should include drafted_trashable
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'includes the published item' do
|
130
|
+
subject.should include published_trashable
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'does not include the trashed item' do
|
134
|
+
subject.should_not include trashed_trashable
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Not affected by this customization
|
139
|
+
describe :published do
|
140
|
+
end
|
141
|
+
|
142
|
+
describe :trashed do
|
143
|
+
before { trashed_trashable.draft_destroy }
|
144
|
+
subject { Trashable.trashed }
|
145
|
+
its(:count) { should eql 1 }
|
146
|
+
|
147
|
+
it 'does not raise an exception' do
|
148
|
+
expect { subject.load }.to_not raise_exception
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'does not include the drafted item' do
|
152
|
+
subject.should_not include drafted_trashable
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'does not include the published item' do
|
156
|
+
subject.should_not include published_trashable
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'includes the trashed item' do
|
160
|
+
subject.should include trashed_trashable
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|