releaf-content 2.0.0 → 2.0.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.
- checksums.yaml +4 -4
- metadata +5 -51
- data/spec/builders/content/nodes/action_dialog_spec.rb +0 -39
- data/spec/builders/content/nodes/content_form_builder_spec.rb +0 -24
- data/spec/builders/content/nodes/form_builder_spec.rb +0 -262
- data/spec/builders/content/nodes/toolbox_builder_spec.rb +0 -77
- data/spec/controllers/releaf/content/nodes_controller_spec.rb +0 -52
- data/spec/features/nodes_services_spec.rb +0 -437
- data/spec/features/nodes_spec.rb +0 -573
- data/spec/fixtures/dummy.png +0 -0
- data/spec/lib/releaf/content/acts_as_node_spec.rb +0 -90
- data/spec/lib/releaf/content/configuration_spec.rb +0 -159
- data/spec/lib/releaf/content/engine_spec.rb +0 -149
- data/spec/lib/releaf/content/node_spec.rb +0 -593
- data/spec/lib/releaf/content/route_spec.rb +0 -229
- data/spec/middleware/routes_reloader_spec.rb +0 -96
- data/spec/routing/node_mapper_spec.rb +0 -311
- data/spec/services/releaf/content/build_route_objects_spec.rb +0 -72
- data/spec/services/releaf/content/node/copy_spec.rb +0 -338
- data/spec/services/releaf/content/node/move_spec.rb +0 -20
- data/spec/services/releaf/content/node/save_under_parent_spec.rb +0 -49
- data/spec/services/releaf/content/node/service_spec.rb +0 -19
- data/spec/validators/content/node/parent_validator_spec.rb +0 -56
- data/spec/validators/content/node/root_validator_spec.rb +0 -69
- data/spec/validators/content/node/singleness_validator_spec.rb +0 -145
@@ -1,72 +0,0 @@
|
|
1
|
-
require "rails_helper"
|
2
|
-
|
3
|
-
describe Releaf::Content::BuildRouteObjects do
|
4
|
-
let(:home_page_node) { create(:home_page_node, id: 23, locale: "lv", slug: "llvv") }
|
5
|
-
let(:node) { create(:text_page_node, id: 27, parent: home_page_node, slug: "some-text") }
|
6
|
-
let(:controller) { Releaf::Content::Route.default_controller( node.class ) }
|
7
|
-
let(:subject) { described_class.new(node_class: node.class, node_content_class: TextPage, default_controller: controller) }
|
8
|
-
|
9
|
-
describe "#call" do
|
10
|
-
it "returns an array" do
|
11
|
-
expect(subject.call).to be_a Array
|
12
|
-
end
|
13
|
-
|
14
|
-
it "returns an array of Node::Route objects" do
|
15
|
-
result = subject.call
|
16
|
-
expect(result.count).to eq(1)
|
17
|
-
expect(result.first.class).to eq(Releaf::Content::Route)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe "#nodes" do
|
22
|
-
it "returns all nodes" do
|
23
|
-
expect(subject.nodes).to match_array([home_page_node, node])
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe "#content_nodes" do
|
28
|
-
it "returns nodes with a specified content class" do
|
29
|
-
expect(subject.content_nodes).to eq([node])
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe "#build_route_object" do
|
34
|
-
let(:route) { subject.build_route_object(node) }
|
35
|
-
|
36
|
-
context "when node is not available" do
|
37
|
-
it "does not include it in return" do
|
38
|
-
allow_any_instance_of(Node).to receive(:available?).and_return(false)
|
39
|
-
expect(route).to be_nil
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
it "returns a route instance" do
|
44
|
-
expect(route).to be_a Releaf::Content::Route
|
45
|
-
end
|
46
|
-
|
47
|
-
it "assigns node_class from given node" do
|
48
|
-
expect(route.node_class).to be Node
|
49
|
-
end
|
50
|
-
|
51
|
-
it "assigns node_id from given node" do
|
52
|
-
expect(route.node_id).to eq "27"
|
53
|
-
end
|
54
|
-
|
55
|
-
it "assigns path from given node" do
|
56
|
-
expect(route.path).to eq "/llvv/some-text"
|
57
|
-
end
|
58
|
-
|
59
|
-
it "assigns locale from given node" do
|
60
|
-
expect(route.locale).to eq "lv"
|
61
|
-
end
|
62
|
-
|
63
|
-
it "assigns default_controller from given argument" do
|
64
|
-
expect(route.default_controller).to be controller
|
65
|
-
end
|
66
|
-
|
67
|
-
it "assigns site from content routing configuration" do
|
68
|
-
allow( Releaf::Content).to receive(:routing).and_return('Node' => {site: 'some_site'})
|
69
|
-
expect(route.site).to eq 'some_site'
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
@@ -1,338 +0,0 @@
|
|
1
|
-
require "rails_helper"
|
2
|
-
|
3
|
-
describe Releaf::Content::Node::Copy do
|
4
|
-
|
5
|
-
let(:root_node) { create(:home_page_node) }
|
6
|
-
|
7
|
-
let(:node) { create(node_factory, parent: root_node) }
|
8
|
-
let(:node_factory) { :text_page_node }
|
9
|
-
|
10
|
-
let(:content_factory) { :text_page }
|
11
|
-
let(:content_attributes) { { } }
|
12
|
-
|
13
|
-
let(:complex_node_factory) { :banner_page_node }
|
14
|
-
let(:complex_content_factory) { :banner_page }
|
15
|
-
let(:complex_content_duplicatable_associations) {
|
16
|
-
[
|
17
|
-
{
|
18
|
-
banner_groups: [
|
19
|
-
{ banners: [] }
|
20
|
-
]
|
21
|
-
}
|
22
|
-
] }
|
23
|
-
|
24
|
-
let(:file) { File.new(File.expand_path('../../../../fixtures/dummy.png', __dir__)) }
|
25
|
-
|
26
|
-
let(:original) { create(content_factory, content_attributes) }
|
27
|
-
|
28
|
-
describe "#call" do
|
29
|
-
subject { described_class.new(node: node, parent_id: root_node.id ) }
|
30
|
-
|
31
|
-
it "returns node" do
|
32
|
-
expect(subject.call.class).to eq(node.class)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe "#make_copy" do
|
37
|
-
# this is a double check to verify file duplication by doing the full copying process.
|
38
|
-
# #duplicate_dragonfly_attachments is tested separately in more detail below
|
39
|
-
subject { described_class.new(node: node, parent_id: root_node.id ) }
|
40
|
-
|
41
|
-
context "when node content has dragonfly file fields" do
|
42
|
-
let(:node_factory) { complex_node_factory }
|
43
|
-
|
44
|
-
it "duplicates dragonfly attachments, storing them as separate files that are no longer linked" do
|
45
|
-
node.content.top_banner = file
|
46
|
-
node.save!
|
47
|
-
copy = subject.make_copy
|
48
|
-
|
49
|
-
# make sure the uids are non-empty and different
|
50
|
-
expect(node.content.top_banner_uid).to be_present
|
51
|
-
expect(copy.content.top_banner_uid).to be_present
|
52
|
-
expect(copy.content.top_banner_uid).to_not eq node.content.top_banner_uid
|
53
|
-
|
54
|
-
# make sure the files are stored and exist
|
55
|
-
expect(copy.content.top_banner.path).to start_with Dragonfly.app.datastore.root_path
|
56
|
-
expect(node.content.class.find(node.content.id).top_banner.path).to start_with Dragonfly.app.datastore.root_path
|
57
|
-
expect(copy.content.top_banner.path).to_not eq node.content.top_banner.path
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
describe "#duplicate_under" do
|
65
|
-
let!(:source_node) { create(:node, locale: "lv") }
|
66
|
-
let!(:target_node) { create(:node, locale: "en") }
|
67
|
-
|
68
|
-
before do
|
69
|
-
allow_any_instance_of(Releaf::Content::Node::RootValidator).to receive(:validate)
|
70
|
-
subject.node = source_node
|
71
|
-
subject.parent_id = target_node.id
|
72
|
-
end
|
73
|
-
|
74
|
-
it "creates duplicated node under target node" do
|
75
|
-
new_node = Node.new
|
76
|
-
duplicated_content = double('content', id: 1234)
|
77
|
-
expect( Node ).to receive(:new).ordered.and_return(new_node)
|
78
|
-
expect( new_node ).to receive(:assign_attributes_from).with(source_node).ordered.and_call_original
|
79
|
-
expect( subject ).to receive(:duplicate_content).ordered.and_return(duplicated_content)
|
80
|
-
expect( new_node ).to receive(:content_id=).with(1234).ordered
|
81
|
-
expect( Releaf::Content::Node::SaveUnderParent ).to receive(:call).with(node: new_node, parent_id: target_node.id)
|
82
|
-
.ordered.and_call_original
|
83
|
-
expect(subject.duplicate_under).to eq(new_node)
|
84
|
-
end
|
85
|
-
|
86
|
-
it "doesn't update settings timestamp" do
|
87
|
-
expect( Node ).to_not receive(:updated)
|
88
|
-
subject.duplicate_under
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
|
-
describe "#duplicate_content" do
|
94
|
-
|
95
|
-
let(:content) { node.content }
|
96
|
-
|
97
|
-
before do
|
98
|
-
allow(subject).to receive(:node).and_return(node)
|
99
|
-
end
|
100
|
-
|
101
|
-
context "when node has a content object" do
|
102
|
-
|
103
|
-
it "calls #duplicate_object with current content" do
|
104
|
-
expect(subject).to receive(:duplicate_object).with(content).and_return(content)
|
105
|
-
subject.duplicate_content
|
106
|
-
end
|
107
|
-
|
108
|
-
it "saves the duplicated result" do
|
109
|
-
new_content = subject.duplicate_content
|
110
|
-
expect(new_content.new_record?).to be false
|
111
|
-
end
|
112
|
-
|
113
|
-
it "returns the newly saved content" do
|
114
|
-
new_content = subject.duplicate_content
|
115
|
-
expect(new_content.id).to_not eq content.id
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
context "when node does not have a content object" do
|
120
|
-
before do
|
121
|
-
node.content = nil
|
122
|
-
end
|
123
|
-
|
124
|
-
it "does nothing" do
|
125
|
-
expect(subject).to_not receive(:duplicate_object)
|
126
|
-
expect(node).to_not receive(:save!)
|
127
|
-
subject.duplicate_content
|
128
|
-
end
|
129
|
-
it "returns nil" do
|
130
|
-
expect(subject.duplicate_content).to be_nil
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
end
|
135
|
-
|
136
|
-
|
137
|
-
describe "#duplicate_object" do
|
138
|
-
|
139
|
-
context "when object has no duplicatable associations" do
|
140
|
-
let(:content_factory) { :text_page }
|
141
|
-
let(:content_attributes) { { text_html: "html" } }
|
142
|
-
|
143
|
-
it "builds an unsaved copy of the object" do
|
144
|
-
copy = subject.duplicate_object(original)
|
145
|
-
expect(copy.class).to be original.class
|
146
|
-
expect(copy.new_record?).to be true
|
147
|
-
|
148
|
-
expect(copy.text_html).to eq original.text_html
|
149
|
-
end
|
150
|
-
|
151
|
-
it "uses #deep_clone for copying" do
|
152
|
-
expect(subject).to receive(:duplicatable_associations).with(original.class).and_call_original
|
153
|
-
expect(original).to receive(:deep_clone).with( include: [] ).and_call_original
|
154
|
-
subject.duplicate_object(original)
|
155
|
-
end
|
156
|
-
|
157
|
-
it "calls #supplement_object_duplication with the original object and its new copy" do
|
158
|
-
copy = original.dup
|
159
|
-
|
160
|
-
# stub #dup (which is called by deep_clone internally) so that it returns a known instance
|
161
|
-
allow(original).to receive(:dup).and_return(copy)
|
162
|
-
|
163
|
-
expect(subject).to receive(:supplement_object_duplication).with(original, copy)
|
164
|
-
subject.duplicate_object(original)
|
165
|
-
end
|
166
|
-
|
167
|
-
end
|
168
|
-
|
169
|
-
context "when object has duplicatable associations" do
|
170
|
-
let(:content_factory) { complex_content_factory }
|
171
|
-
|
172
|
-
let(:content_attributes) do
|
173
|
-
{
|
174
|
-
intro_text_html: "Intro html",
|
175
|
-
banner_groups_attributes: [
|
176
|
-
{
|
177
|
-
title: "Group title",
|
178
|
-
banners_attributes: [
|
179
|
-
url: "Banner url"
|
180
|
-
]
|
181
|
-
},
|
182
|
-
]
|
183
|
-
}
|
184
|
-
end
|
185
|
-
|
186
|
-
it "passes duplicatable associations to #deep_clone" do
|
187
|
-
expect(original).to receive(:deep_clone).with( include: complex_content_duplicatable_associations ).and_call_original
|
188
|
-
subject.duplicate_object(original)
|
189
|
-
end
|
190
|
-
|
191
|
-
it "builds an unsaved copy with nested copies of associated objects" do
|
192
|
-
copy = subject.duplicate_object(original)
|
193
|
-
expect(copy.class).to be original.class
|
194
|
-
expect(copy.new_record?).to be true
|
195
|
-
expect(copy.intro_text_html).to eq original.intro_text_html
|
196
|
-
|
197
|
-
original_item = original.banner_groups.first
|
198
|
-
copied_item = copy.banner_groups.first
|
199
|
-
expect(copied_item.class).to be original_item.class
|
200
|
-
expect(copied_item.new_record?).to be true
|
201
|
-
expect(copied_item.title).to eq original_item.title
|
202
|
-
|
203
|
-
original_nested_item = original.banner_groups.first.banners.first
|
204
|
-
copied_nested_item = copy.banner_groups.first.banners.first
|
205
|
-
expect(copied_nested_item.class).to be original_nested_item.class
|
206
|
-
expect(copied_nested_item.new_record?).to be true
|
207
|
-
expect(copied_nested_item.url).to eq original_nested_item.url
|
208
|
-
end
|
209
|
-
|
210
|
-
it "calls #supplement_object_duplication on all cloned objects" do
|
211
|
-
original_item = original.banner_groups.first
|
212
|
-
original_nested_item = original_item.banners.first
|
213
|
-
|
214
|
-
expect(subject).to receive(:supplement_object_duplication).with(original, kind_of(original.class))
|
215
|
-
expect(subject).to receive(:supplement_object_duplication).with(original_item, kind_of(original_item.class))
|
216
|
-
expect(subject).to receive(:supplement_object_duplication).with(original_nested_item, kind_of(original_nested_item.class))
|
217
|
-
subject.duplicate_object(original)
|
218
|
-
end
|
219
|
-
|
220
|
-
end
|
221
|
-
|
222
|
-
end
|
223
|
-
|
224
|
-
describe "#supplement_object_duplication" do
|
225
|
-
it "calls #duplicate_dragonfly_attachments with given original and copy" do
|
226
|
-
expect(subject).to receive(:duplicate_dragonfly_attachments).with(:foo, :bar)
|
227
|
-
subject.supplement_object_duplication(:foo, :bar)
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
describe "#duplicatable_associations" do
|
232
|
-
let(:content_class) { build(content_factory).class }
|
233
|
-
|
234
|
-
it "uses Releaf::ResourceBase to detect duplicatable associations" do
|
235
|
-
expect(Releaf::ResourceBase).to receive(:new).with(content_class).and_call_original
|
236
|
-
subject.duplicatable_associations(content_class)
|
237
|
-
end
|
238
|
-
|
239
|
-
context "when given class has duplicatable associations" do
|
240
|
-
it "returns duplicatable association names as nested arrays of hashes" do
|
241
|
-
expect(subject.duplicatable_associations(content_class)).to eq []
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
context "when given class has no duplicatable associations" do
|
246
|
-
let(:content_factory) { complex_content_factory }
|
247
|
-
it "returns an empty array" do
|
248
|
-
expect(subject.duplicatable_associations(content_class)).to eq complex_content_duplicatable_associations
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
|
254
|
-
describe "#duplicate_dragonfly_attachments" do
|
255
|
-
let(:content_factory) { complex_content_factory }
|
256
|
-
let(:copy) { original.dup }
|
257
|
-
|
258
|
-
context "when the original object's dragonfly attributes" do
|
259
|
-
|
260
|
-
context "are blank" do
|
261
|
-
it "sets the file attributes to nil on the given copy" do
|
262
|
-
expect(copy).to receive(:top_banner_uid=).with(nil).ordered
|
263
|
-
expect(copy).to receive(:top_banner=).with(nil).ordered
|
264
|
-
subject.duplicate_dragonfly_attachments(original, copy)
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
context "contain files" do
|
269
|
-
|
270
|
-
it "separates the attachments so that dragonfly treats them as separate files" do
|
271
|
-
# it is important that the owner class used in this test has at least two dragonfly attributes
|
272
|
-
# and the test is not using the first one.
|
273
|
-
# (an earlier implementation worked only with the first file
|
274
|
-
# and would have passed the test if the test used the first file)
|
275
|
-
expect(original.dragonfly_attachments.keys.find_index(:bottom_banner)).to be > 0
|
276
|
-
|
277
|
-
original.bottom_banner = file
|
278
|
-
original.save!
|
279
|
-
|
280
|
-
subject.duplicate_dragonfly_attachments(original, copy)
|
281
|
-
copy.save!
|
282
|
-
|
283
|
-
# refetch the objects. calling #reload on them is not enough
|
284
|
-
original_id = original.id
|
285
|
-
copy_id = copy.id
|
286
|
-
klass = original.class
|
287
|
-
|
288
|
-
original = klass.find(original_id)
|
289
|
-
copy = klass.find(copy_id)
|
290
|
-
|
291
|
-
# make sure the uids are non-empty and different
|
292
|
-
expect(original.bottom_banner_uid).to be_present
|
293
|
-
expect(copy.bottom_banner_uid).to be_present
|
294
|
-
expect(copy.bottom_banner_uid).to_not eq original.bottom_banner_uid
|
295
|
-
|
296
|
-
# make sure the files are stored and exist
|
297
|
-
expect(copy.bottom_banner.path).to start_with Dragonfly.app.datastore.root_path
|
298
|
-
expect(original.bottom_banner.path).to start_with Dragonfly.app.datastore.root_path
|
299
|
-
expect(copy.bottom_banner.path).to_not eq original.bottom_banner.path
|
300
|
-
|
301
|
-
# make sure the metadata is readable as well
|
302
|
-
expect(copy.bottom_banner.format).to eq original.bottom_banner.format
|
303
|
-
end
|
304
|
-
|
305
|
-
end
|
306
|
-
|
307
|
-
context "contain files that are missing" do
|
308
|
-
|
309
|
-
it "sets the file attributes to nil on the given copy" do
|
310
|
-
original.top_banner = file
|
311
|
-
original.save!
|
312
|
-
|
313
|
-
original_id = original.id
|
314
|
-
|
315
|
-
# simulate deletion from filesystem by setting the uid to an invalid path
|
316
|
-
original.top_banner_uid = "xxx" + original.top_banner_uid
|
317
|
-
original.save!
|
318
|
-
|
319
|
-
klass = original.class
|
320
|
-
original = klass.find(original_id)
|
321
|
-
|
322
|
-
subject.duplicate_dragonfly_attachments(original, copy)
|
323
|
-
copy.save!
|
324
|
-
copy_id = copy.id
|
325
|
-
copy = klass.find(copy_id)
|
326
|
-
|
327
|
-
expect(copy.top_banner_uid).to be_nil
|
328
|
-
expect(copy.top_banner).to be_nil
|
329
|
-
end
|
330
|
-
|
331
|
-
end
|
332
|
-
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require "rails_helper"
|
2
|
-
|
3
|
-
describe Releaf::Content::Node::Move do
|
4
|
-
class DummyNodeServiceIncluder
|
5
|
-
include Releaf::Content::Node::Service
|
6
|
-
end
|
7
|
-
|
8
|
-
let(:node){ Node.new }
|
9
|
-
subject{ described_class.new(node: node, parent_id: 12) }
|
10
|
-
|
11
|
-
describe "#call" do
|
12
|
-
context "when parent is same" do
|
13
|
-
it "does nothing and returns self" do
|
14
|
-
node.parent_id = 12
|
15
|
-
expect(node.class).to_not receive(:transaction)
|
16
|
-
expect(subject.call).to eq(node)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
require "rails_helper"
|
2
|
-
|
3
|
-
describe Releaf::Content::Node::SaveUnderParent do
|
4
|
-
class DummyNodeServiceIncluder
|
5
|
-
include Releaf::Content::Node::Service
|
6
|
-
end
|
7
|
-
|
8
|
-
let(:root_node){ create(:node, locale: "lv") }
|
9
|
-
let(:node){ build(:text_page_node) }
|
10
|
-
subject{ described_class.new(node: node, parent_id: root_node.id) }
|
11
|
-
|
12
|
-
describe "#call" do
|
13
|
-
it "saves node nuder node with given node_id" do
|
14
|
-
node2 = create(:text_page_node, parent: root_node)
|
15
|
-
|
16
|
-
subject.parent_id = node2.id
|
17
|
-
subject.call
|
18
|
-
expect( node ).to_not be_new_record
|
19
|
-
expect( node.parent ).to eq node2
|
20
|
-
end
|
21
|
-
|
22
|
-
it "maintains node name and slug, then saves record" do
|
23
|
-
expect( node ).to receive(:maintain_name).ordered.and_call_original
|
24
|
-
expect( node ).to receive(:maintain_slug).ordered.and_call_original
|
25
|
-
expect( node ).to receive(:save!).ordered.and_call_original
|
26
|
-
subject.call
|
27
|
-
end
|
28
|
-
|
29
|
-
context "when #validate_root_locale_uniqueness? returns true" do
|
30
|
-
let(:node){ root_node }
|
31
|
-
|
32
|
-
it "sets locale to nil" do
|
33
|
-
allow(node).to receive(:validate_root_locale_uniqueness?).and_return(true)
|
34
|
-
subject.parent_id = nil
|
35
|
-
expect { subject.call }.to change{ node.locale }.from("lv").to(nil)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context "when #validate_root_locale_uniqueness? returns false" do
|
40
|
-
let(:node){ root_node }
|
41
|
-
|
42
|
-
it "doesn't set locale to nil" do
|
43
|
-
allow(node).to receive(:validate_root_locale_uniqueness?).and_return(false)
|
44
|
-
subject.parent_id = nil
|
45
|
-
expect { subject.call }.to_not change{ node.locale }
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|