releaf-content 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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