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.
@@ -1,52 +0,0 @@
1
- require 'rails_helper'
2
-
3
- describe Releaf::Content::NodesController do
4
-
5
- describe "#features"do
6
- it "excludes `create another` and `search` features" do
7
- expect(subject.features).to_not include(:create_another, :search)
8
- end
9
- end
10
-
11
- describe "#ancestor_nodes" do
12
- let(:node){ Node.new }
13
- let(:ancestors){ Node.where(id: 1212) }
14
-
15
- before do
16
- allow(ancestors).to receive(:reorder).with(:depth).and_return(["depth_ordered_ancestors"])
17
- end
18
-
19
- context "when new node" do
20
- context "when node has parent" do
21
- it "returns parent ancestors ordered by depth alongside parent ancestor" do
22
- parent_node = Node.new
23
- node.parent = parent_node
24
- allow(parent_node).to receive(:ancestors).and_return(ancestors)
25
- expect(subject.ancestor_nodes(node)).to eq(["depth_ordered_ancestors", parent_node])
26
- end
27
- end
28
-
29
- context "when node has no parent" do
30
- it "returns empty array" do
31
- expect(subject.ancestor_nodes(node)).to eq([])
32
- end
33
- end
34
- end
35
-
36
- context "when persisted node" do
37
- it "returns resource ancestors ordered by depth" do
38
- allow(node).to receive(:persisted?).and_return(true)
39
- allow(node).to receive(:ancestors).and_return(ancestors)
40
- expect(subject.ancestor_nodes(node)).to eq(["depth_ordered_ancestors"])
41
- end
42
- end
43
- end
44
-
45
- describe ".resource_class" do
46
- it "looks up node class in releaf content resource configuration" do
47
- config = { 'OtherSite::OtherNode' => { controller: 'Releaf::Content::NodesController' } }
48
- allow( Releaf::Content ).to receive(:resources).and_return(config)
49
- expect( described_class.resource_class ).to be OtherSite::OtherNode
50
- end
51
- end
52
- end
@@ -1,437 +0,0 @@
1
- require 'rails_helper'
2
- describe "Nodes services (copy, move)" do
3
-
4
- describe "Moving" do
5
- before do
6
- @home_page_node = create(:home_page_node, locale: "lv")
7
- @home_page_node_2 = create(:home_page_node, locale: "en")
8
- @text_page_node_3 = create(:text_page_node, parent_id: @home_page_node_2.id)
9
- @text_page_node_4 = create(:text_page_node, parent_id: @text_page_node_3.id)
10
-
11
- # it is important to reload nodes, otherwise associations will return empty set
12
- @home_page_node.reload
13
- @home_page_node_2.reload
14
- @text_page_node_3.reload
15
- @text_page_node_4.reload
16
- end
17
-
18
- context "when one of children becomes invalid" do
19
- before do
20
- @text_page_node_4.name = nil
21
- @text_page_node_4.save(validate: false)
22
- end
23
-
24
- it "raises ActiveRecord::RecordInvalid" do
25
- expect { @text_page_node_3.move(@home_page_node.id) }.to raise_error ActiveRecord::RecordInvalid
26
- end
27
-
28
- it "raises error on node being moved, even tought descendant has error" do
29
- begin
30
- @text_page_node_3.move(@home_page_node.id)
31
- rescue ActiveRecord::RecordInvalid => e
32
- expect( e.record ).to eq @text_page_node_3
33
- end
34
-
35
- expect(@text_page_node_3.errors.messages).to eq(name: [], base: ["descendant invalid"])
36
- end
37
- end
38
-
39
- context "when moving existing node to other nodes child's position" do
40
- it "changes parent_id" do
41
- expect{ @text_page_node_3.move(@home_page_node.id) }.to change{ Node.find(@text_page_node_3.id).parent_id }.from(@home_page_node_2.id).to(@home_page_node.id)
42
- end
43
- end
44
-
45
- context "when moving to self child's position" do
46
- it "raises ActiveRecord::RecordInvalid" do
47
- expect{ @text_page_node_3.move(@text_page_node_3.id) }.to raise_error(ActiveRecord::RecordInvalid)
48
- end
49
- end
50
-
51
- context "when passing nil as target node" do
52
- it "updates parent_id" do
53
- allow_any_instance_of(Releaf::Content::Node::RootValidator).to receive(:validate)
54
- @home_page_node.destroy
55
- expect{ @text_page_node_3.move(nil) }.to change { Node.find(@text_page_node_3.id).parent_id }.to(nil)
56
- end
57
- end
58
-
59
- context "when passing nonexistent target node's id" do
60
- it "raises ActiveRecord::RecordInvalid" do
61
- expect{ @text_page_node_3.move(998123) }.to raise_error(ActiveRecord::RecordInvalid)
62
- end
63
- end
64
-
65
- end
66
-
67
- describe "Node copying", create_nodes: true do
68
- before create_nodes: true do
69
- @home_page_node = create(:home_page_node, locale: "lv")
70
- @home_page_node_2 = create(:home_page_node, locale: "en")
71
- @text_page_node_3 = create(:text_page_node, parent_id: @home_page_node_2.id)
72
- @text_page_node_4 = create(:text_page_node, parent_id: @text_page_node_3.id)
73
- @text_page_node_5 = create(:text_page_node, parent_id: @text_page_node_4.id)
74
-
75
- # it is important to reload nodes, otherwise associations will return empty set
76
- @home_page_node.reload
77
- @home_page_node_2.reload
78
- @text_page_node_3.reload
79
- @text_page_node_4.reload
80
- end
81
-
82
- context "when one of children becomes invalid" do
83
- before do
84
- @text_page_node_4.name = nil
85
- @text_page_node_4.save(validate: false)
86
- end
87
-
88
- it "raises ActiveRecord::RecordInvalid" do
89
- expect { @text_page_node_3.copy(@home_page_node.id) }.to raise_error ActiveRecord::RecordInvalid
90
- end
91
-
92
- it "raises error on node being copied" do
93
- begin
94
- @text_page_node_3.copy(@home_page_node.id)
95
- rescue ActiveRecord::RecordInvalid => e
96
- expect( e.record ).to eq @text_page_node_3
97
- end
98
- expect(@text_page_node_3.errors.messages).to eq(name: [], base: ["descendant invalid"])
99
- end
100
-
101
- it "doesn't create any new nodes" do
102
- expect do
103
- begin
104
- @text_page_node_3.copy(@home_page_node.id)
105
- rescue ActiveRecord::RecordInvalid
106
- end
107
- end.to_not change { Node.count }
108
- end
109
-
110
- it "doesn't update settings timestamp" do
111
- expect( Node ).to_not receive(:updated)
112
- begin
113
- @text_page_node_3.copy(@home_page_node.id)
114
- rescue ActiveRecord::RecordInvalid
115
- end
116
- end
117
-
118
- end
119
-
120
-
121
- context "with corect parent_id" do
122
- it "creates node along with descendant nodes" do
123
- expect{ @text_page_node_3.copy(@home_page_node.id) }.to change{ Node.count }.by( @text_page_node_3.descendants.size + 1 )
124
- end
125
-
126
- it "correctly copies attributes" do
127
- allow( @text_page_node_3 ).to receive(:children).and_return([@text_page_node_4])
128
- allow( @text_page_node_4 ).to receive(:children).and_return([@text_page_node_5])
129
-
130
- @text_page_node_3.update_attribute(:active, false)
131
- @text_page_node_4.update_attribute(:active, false)
132
-
133
- allow( @text_page_node_3 ).to receive(:attributes_to_copy).and_return(["name", "parent_id", "content_type"])
134
-
135
- @text_page_node_3.copy(@home_page_node.id)
136
-
137
- @node_2_copy = @home_page_node.children.first
138
- @node_3_copy = @node_2_copy.children.first
139
- @node_4_copy = @node_3_copy.children.first
140
-
141
- # new nodes by default are active, however we stubbed
142
- # #attributes_to_copy of @test_node_2 to not return active attribute
143
- # Also we updated @test_node_2#active to be false.
144
- # However copy is active, because active attribute wasn't copied
145
- expect( @node_2_copy ).to be_active
146
- # for copy of @text_page_node_3 active attribute was copied however, as it
147
- # should have been
148
- expect( @node_3_copy ).to_not be_active
149
- expect( @node_4_copy ).to be_active
150
-
151
- expect( @node_2_copy.name ).to eq @text_page_node_3.name
152
- expect( @node_3_copy.name ).to eq @text_page_node_4.name
153
- expect( @node_4_copy.name ).to eq @text_page_node_5.name
154
- end
155
-
156
- it "updates settings timestamp only once" do
157
- expect( Node ).to receive(:updated).once.and_call_original
158
- @text_page_node_3.copy(@home_page_node.id)
159
- end
160
-
161
- context "when parent_id is nil" do
162
- it "creates new node" do
163
- allow_any_instance_of(Releaf::Content::Node::RootValidator).to receive(:validate)
164
- expect{ @text_page_node_3.copy(nil) }.to change{ Node.count }.by(3)
165
- end
166
- end
167
-
168
- context "when copying root nodes", create_nodes: false do
169
- context "when root locale uniqueness is validated" do
170
- it "resets locale to nil" do
171
- @text_page_node = create(:home_page_node, locale: 'en')
172
- allow_any_instance_of(Node).to receive(:validate_root_locale_uniqueness?).and_return(true)
173
- @text_page_node.copy(nil)
174
- expect( Node.last.locale ).to eq nil
175
- end
176
- end
177
-
178
- context "when root locale uniqueness is not validated" do
179
- it "doesn't reset locale to nil" do
180
- @text_page_node = create(:home_page_node, locale: 'en')
181
- allow_any_instance_of(Node).to receive(:validate_root_locale_uniqueness?).and_return(false)
182
- @text_page_node.copy(nil)
183
- expect( Node.last.locale ).to eq 'en'
184
- end
185
- end
186
- end
187
- end
188
-
189
- context "with nonexistent parent_id" do
190
- it "raises ActiveRecord::RecordInvalid" do
191
- expect { @text_page_node_3.copy(99991) }.to raise_error(ActiveRecord::RecordInvalid)
192
- end
193
- end
194
-
195
- context "with same parent_id as node.id" do
196
- it "raises ActiveRecord::RecordInvalid" do
197
- expect{ @text_page_node_3.copy(@text_page_node_3.id) }.to raise_error(ActiveRecord::RecordInvalid)
198
- end
199
- end
200
-
201
- context "when copying to child node" do
202
- it "raises ActiveRecord::RecordInvalid" do
203
- expect{ @text_page_node_3.copy(@text_page_node_4.id) }.to raise_error(ActiveRecord::RecordInvalid)
204
- end
205
- end
206
-
207
- describe "slug handling" do
208
-
209
- before do
210
- @nodes = {}
211
-
212
- @nodes[:parent_one] = create(:text_page_node, parent: @home_page_node)
213
- @nodes[:parent_two] = create(:text_page_node, parent: @home_page_node)
214
-
215
- @nodes[:child] = create(:text_page_node, parent: @nodes[:parent_one], slug: "child-slug")
216
- @nodes[:grandchild] = create(:text_page_node, parent: @nodes[:child], slug: "grandchild-slug")
217
- @nodes[:great_grandchild] = create(:text_page_node, parent: @nodes[:grandchild], slug: "great-grandchild-slug")
218
-
219
- @nodes[:other_child] = create(:text_page_node, parent: @nodes[:parent_two], slug: "other-child-slug")
220
- end
221
-
222
- context "when copying a node tree to a parent that already has a child node with the same slug" do
223
- it "adds incremental index to the slug of the main copied node, preserving slugs of deeper descendants" do
224
- @nodes[:other_child].update! slug: "child-slug"
225
- @nodes[:child].copy( @nodes[:parent_two].id )
226
-
227
- copy = @nodes[:parent_two].children.last
228
-
229
- expect(copy.slug).to eq "child-slug-1"
230
- expect(copy.children.map(&:slug)).to eq ["grandchild-slug"]
231
- expect(copy.children.first.children.map(&:slug)).to eq ["great-grandchild-slug"]
232
-
233
- end
234
- end
235
-
236
- context "when copying a node tree to a parent that does not have a child node with the same slug" do
237
- it "copies slugs without any changes" do
238
- @nodes[:child].copy( @nodes[:parent_two].id )
239
- copy = @nodes[:parent_two].children.last
240
-
241
- expect(copy.slug).to eq "child-slug"
242
-
243
- expect(copy.children.map(&:slug)).to eq ["grandchild-slug"]
244
- expect(copy.children.first.children.map(&:slug)).to eq ["great-grandchild-slug"]
245
- end
246
- end
247
-
248
- end
249
-
250
- end
251
-
252
-
253
- feature "Deep copying of content nodes", js: true do
254
-
255
- let(:node_class) { Node }
256
- let(:locale) { "en" }
257
-
258
- background do
259
- Rails.cache.clear
260
- # preload ActsAsNode classes
261
- Rails.application.eager_load!
262
-
263
- create(:home_page_node, name: "Root page", locale: "en", slug: "en")
264
- auth_as_user
265
- end
266
-
267
- def expect_different_values original, copy
268
- expect(original).to be_present
269
- expect(copy).to be_present
270
- expect(original).to_not eq copy
271
- end
272
-
273
- scenario "Deep copying of content nodes with nested associations and files" do
274
- visit "/admin/nodes/"
275
- open_toolbox("Add child", node_class.first, ".view-index .collection li")
276
-
277
- dummy_file_path = File.expand_path('../fixtures/dummy.png', __dir__)
278
-
279
- within('.dialog.content-type.initialized') do
280
- click_link "Banner page"
281
- end
282
-
283
- expect(page).to have_css('input[type="text"][name="resource[content_type]"][value="Banner page"]')
284
-
285
- fill_in 'Name', with: "Banner page"
286
- fill_in 'Slug', with: "banner-page"
287
-
288
- attach_file('Top banner', dummy_file_path)
289
- attach_file('Bottom banner', dummy_file_path)
290
-
291
- within('section.nested[data-name="banner_groups"]') do
292
- add_nested_item "banner_groups", 0 do
293
- fill_in "Title", with: "Banner group 1 title"
294
-
295
- within('section.nested[data-name="banners"]') do
296
- add_nested_item "banners", 0 do
297
- attach_file('Image', dummy_file_path)
298
- fill_in "Url", with: "Banner-1-url"
299
- end
300
- add_nested_item "banners", 1 do
301
- attach_file('Image', dummy_file_path)
302
- fill_in "Url", with: "Banner-2-url"
303
- end
304
- end
305
- end
306
-
307
- add_nested_item "banner_groups", 1 do
308
- fill_in "Title", with: "Banner group 2 title"
309
- end
310
- end
311
-
312
- wait_for_all_richtexts
313
- save_and_check_response "Create succeeded"
314
-
315
- open_toolbox("Copy")
316
-
317
- within('.dialog.copy.initialized') do
318
- find('label', text: "Root page").click
319
- click_button "Copy"
320
- end
321
-
322
- expect(page).to have_css('body > .notifications .notification[data-id="resource_status"][data-type="success"]', text: "Copy succeeded")
323
-
324
- # verify record count in db
325
- expect(node_class.where(content_type: 'BannerPage').count).to eq 2
326
- expect(BannerGroup.count).to eq 4
327
- expect(Banner.count).to eq 4
328
-
329
-
330
- # verify that direct and nested files are duplicated correctly
331
- [
332
- { original: BannerPage.first, copy: BannerPage.last, accessor: :top_banner },
333
- { original: BannerPage.first, copy: BannerPage.last, accessor: :bottom_banner },
334
- {
335
- original: BannerPage.first.banner_groups.first.banners.first,
336
- copy: BannerPage.last.banner_groups.first.banners.first,
337
- accessor: :image
338
- }
339
- ].each do |entry|
340
- original = entry[:original]
341
- copy = entry[:copy]
342
- accessor = entry[:accessor]
343
- expect(original.id).to_not eq copy.id
344
-
345
- # verify that uids exist and are different
346
- expect_different_values(original.send("#{accessor}_uid"), copy.send("#{accessor}_uid"))
347
-
348
- # verify files exist and are different
349
- original_file = original.send(accessor)
350
- copied_file = copy.send(accessor)
351
-
352
- expect_different_values(original_file.path, copied_file.path)
353
- expect(original_file.path).to start_with Dragonfly.app.datastore.root_path
354
- expect(copied_file.path).to start_with Dragonfly.app.datastore.root_path
355
- expect(File.exist?(original_file.path)).to be true
356
- expect(File.exist?(copied_file.path)).to be true
357
- end
358
-
359
-
360
- # change values in the copied node to make sure associations are not linked
361
- original_id = node_class.where(content_type: "BannerPage").order(:item_position).first.id
362
- copy_id = node_class.where(content_type: "BannerPage").order(:item_position).last.id
363
- expect(copy_id).to_not eq original_id
364
-
365
- visit "/admin/nodes/#{copy_id}/edit/"
366
-
367
- within('section.nested[data-name="banner_groups"]') do
368
- within('.item[data-name="banner_groups"][data-index="0"]') do
369
- expect(page).to have_field('Title', with: 'Banner group 1 title')
370
- fill_in "Title", with: "Copied banner group 1 title"
371
-
372
- within('.item[data-name="banners"][data-index="0"]') do
373
- expect(page).to have_field('Url', with: 'Banner-1-url')
374
- fill_in "Url", with: "Copied-banner-1-url"
375
- end
376
- within('.item[data-name="banners"][data-index="1"]') do
377
- expect(page).to have_field('Url', with: 'Banner-2-url')
378
- fill_in "Url", with: "Copied-banner-2-url"
379
- end
380
- end
381
- within('.item[data-name="banner_groups"][data-index="1"]') do
382
- expect(page).to have_field('Title', with: 'Banner group 2 title')
383
- fill_in "Title", with: "Copied banner group 2 title"
384
- end
385
- end
386
-
387
- copied_file_urls = {
388
- top_banner: find('.field[data-name="top_banner"]').find_link[:href],
389
- bottom_banner: find('.field[data-name="bottom_banner"]').find_link[:href],
390
- nested_banner: find('.item[data-name="banner_groups"][data-index="0"] .item[data-name="banners"][data-index="0"] .field[data-name="image"]').find_link[:href]
391
- }
392
-
393
- wait_for_all_richtexts
394
- save_and_check_response "Update succeeded"
395
-
396
- # verify that the original banner page still has the old values
397
- visit "/admin/nodes/#{original_id}/edit/"
398
-
399
- within('section.nested[data-name="banner_groups"]') do
400
- within('.item[data-name="banner_groups"][data-index="0"]') do
401
- expect(page).to have_field('Title', with: 'Banner group 1 title')
402
-
403
- within('.item[data-name="banners"][data-index="0"]') do
404
- expect(page).to have_field('Url', with: 'Banner-1-url')
405
- end
406
- within('.item[data-name="banners"][data-index="1"]') do
407
- expect(page).to have_field('Url', with: 'Banner-2-url')
408
- end
409
- end
410
- within('.item[data-name="banner_groups"][data-index="1"]') do
411
- expect(page).to have_field('Title', with: 'Banner group 2 title')
412
- end
413
- end
414
-
415
- original_file_urls = {
416
- top_banner: find('.field[data-name="top_banner"]').find_link[:href],
417
- bottom_banner: find('.field[data-name="bottom_banner"]').find_link[:href],
418
- nested_banner: find('.item[data-name="banner_groups"][data-index="0"] .item[data-name="banners"][data-index="0"] .field[data-name="image"]').find_link[:href]
419
- }
420
-
421
- # make sure that original and copied file urls are different and working
422
- original_file_urls.each do |key, original_url|
423
- expect_different_values(original_url, copied_file_urls[key])
424
-
425
- [original_url, copied_file_urls[key]].each do |file_url|
426
- tmpfile = download_file(file_url)
427
- expect(Digest::SHA256.file(tmpfile)).to eq(Digest::SHA256.file(dummy_file_path))
428
- end
429
- end
430
-
431
- end
432
-
433
- end
434
-
435
-
436
-
437
- end