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.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +3 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/CHANGELOG.md +5 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +97 -0
  9. data/LICENSE +20 -0
  10. data/README.md +506 -0
  11. data/Rakefile +6 -0
  12. data/draftsman.gemspec +33 -0
  13. data/lib/draftsman/config.rb +13 -0
  14. data/lib/draftsman/draft.rb +289 -0
  15. data/lib/draftsman/frameworks/cucumber.rb +7 -0
  16. data/lib/draftsman/frameworks/rails.rb +58 -0
  17. data/lib/draftsman/frameworks/rspec.rb +16 -0
  18. data/lib/draftsman/frameworks/sinatra.rb +31 -0
  19. data/lib/draftsman/model.rb +428 -0
  20. data/lib/draftsman/serializers/json.rb +17 -0
  21. data/lib/draftsman/serializers/yaml.rb +17 -0
  22. data/lib/draftsman/version.rb +3 -0
  23. data/lib/draftsman.rb +101 -0
  24. data/lib/generators/draftsman/install_generator.rb +27 -0
  25. data/lib/generators/draftsman/templates/add_object_changes_column_to_drafts.rb +9 -0
  26. data/lib/generators/draftsman/templates/config/initializers/draftsman.rb +11 -0
  27. data/lib/generators/draftsman/templates/create_drafts.rb +22 -0
  28. data/spec/controllers/informants_controller_spec.rb +27 -0
  29. data/spec/controllers/users_controller_spec.rb +23 -0
  30. data/spec/controllers/whodunnits_controller_spec.rb +24 -0
  31. data/spec/draftsman_spec.rb +19 -0
  32. data/spec/dummy/Rakefile +7 -0
  33. data/spec/dummy/app/assets/images/rails.png +0 -0
  34. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  35. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  36. data/spec/dummy/app/controllers/application_controller.rb +20 -0
  37. data/spec/dummy/app/controllers/informants_controller.rb +8 -0
  38. data/spec/dummy/app/controllers/users_controller.rb +8 -0
  39. data/spec/dummy/app/controllers/whodunnits_controller.rb +8 -0
  40. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  41. data/spec/dummy/app/helpers/messages_helper.rb +2 -0
  42. data/spec/dummy/app/mailers/.gitkeep +0 -0
  43. data/spec/dummy/app/models/bastard.rb +3 -0
  44. data/spec/dummy/app/models/child.rb +4 -0
  45. data/spec/dummy/app/models/parent.rb +5 -0
  46. data/spec/dummy/app/models/trashable.rb +3 -0
  47. data/spec/dummy/app/models/vanilla.rb +3 -0
  48. data/spec/dummy/app/models/whitelister.rb +3 -0
  49. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  50. data/spec/dummy/config/application.rb +37 -0
  51. data/spec/dummy/config/boot.rb +6 -0
  52. data/spec/dummy/config/database.yml +25 -0
  53. data/spec/dummy/config/environment.rb +5 -0
  54. data/spec/dummy/config/environments/development.rb +32 -0
  55. data/spec/dummy/config/environments/production.rb +73 -0
  56. data/spec/dummy/config/environments/test.rb +39 -0
  57. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  58. data/spec/dummy/config/initializers/inflections.rb +15 -0
  59. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  60. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  61. data/spec/dummy/config/initializers/session_store.rb +8 -0
  62. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  63. data/spec/dummy/config/locales/en.yml +5 -0
  64. data/spec/dummy/config/routes.rb +6 -0
  65. data/spec/dummy/config.ru +4 -0
  66. data/spec/dummy/db/migrate/20110208155312_set_up_test_tables.rb +86 -0
  67. data/spec/dummy/db/schema.rb +106 -0
  68. data/spec/dummy/db/seeds.rb +7 -0
  69. data/spec/dummy/lib/assets/.gitkeep +0 -0
  70. data/spec/dummy/lib/tasks/.gitkeep +0 -0
  71. data/spec/dummy/log/.gitkeep +0 -0
  72. data/spec/dummy/public/404.html +26 -0
  73. data/spec/dummy/public/422.html +26 -0
  74. data/spec/dummy/public/500.html +25 -0
  75. data/spec/dummy/public/favicon.ico +0 -0
  76. data/spec/dummy/script/rails +6 -0
  77. data/spec/models/child_spec.rb +205 -0
  78. data/spec/models/draft_spec.rb +297 -0
  79. data/spec/models/parent_spec.rb +191 -0
  80. data/spec/models/trashable_spec.rb +164 -0
  81. data/spec/models/vanilla_spec.rb +201 -0
  82. data/spec/models/whitelister_spec.rb +262 -0
  83. data/spec/spec_helper.rb +52 -0
  84. 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