releaf-content 0.2.1 → 1.0.3

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +19 -21
  3. data/app/assets/javascripts/{releaf/controllers → controllers}/releaf/content/nodes.js +0 -0
  4. data/app/assets/stylesheets/{releaf/controllers → controllers}/releaf/content/nodes.scss +0 -0
  5. data/app/builders/releaf/content/builders/action_dialog.rb +9 -1
  6. data/app/builders/releaf/content/builders/tree.rb +1 -1
  7. data/app/builders/releaf/content/content_type_dialog_builder.rb +2 -2
  8. data/app/builders/releaf/content/nodes/form_builder.rb +3 -3
  9. data/app/builders/releaf/content/nodes/index_builder.rb +1 -1
  10. data/app/builders/releaf/content/nodes/toolbox_builder.rb +0 -5
  11. data/app/controllers/releaf/content/nodes_controller.rb +109 -129
  12. data/app/middleware/releaf/content/routes_reloader.rb +12 -4
  13. data/app/services/releaf/content/node/copy.rb +90 -0
  14. data/app/services/releaf/content/node/move.rb +21 -0
  15. data/app/services/releaf/content/node/save_under_parent.rb +22 -0
  16. data/app/services/releaf/content/node/service.rb +17 -0
  17. data/app/validators/releaf/content/node/singleness_validator.rb +1 -24
  18. data/lib/releaf-content.rb +85 -6
  19. data/lib/releaf/content/acts_as_node.rb +0 -5
  20. data/lib/releaf/content/acts_as_node/active_record/acts/node.rb +2 -8
  21. data/lib/releaf/content/configuration.rb +61 -0
  22. data/lib/releaf/content/engine.rb +1 -34
  23. data/lib/releaf/content/node.rb +30 -101
  24. data/lib/releaf/content/node_mapper.rb +28 -2
  25. data/lib/releaf/content/route.rb +37 -25
  26. data/spec/builders/content/nodes/action_dialog_spec.rb +39 -0
  27. data/spec/builders/content/nodes/form_builder_spec.rb +47 -3
  28. data/spec/builders/content/nodes/toolbox_builder_spec.rb +1 -32
  29. data/spec/controllers/releaf/content/nodes_controller_spec.rb +42 -11
  30. data/spec/features/nodes_services_spec.rb +207 -0
  31. data/spec/features/nodes_spec.rb +328 -30
  32. data/spec/lib/releaf/content/acts_as_node_spec.rb +4 -32
  33. data/spec/lib/releaf/content/configuration_spec.rb +159 -0
  34. data/spec/lib/releaf/content/engine_spec.rb +149 -0
  35. data/spec/lib/releaf/content/node_spec.rb +66 -324
  36. data/spec/lib/releaf/content/route_spec.rb +223 -34
  37. data/spec/middleware/routes_reloader_spec.rb +62 -14
  38. data/spec/routing/node_mapper_spec.rb +223 -55
  39. data/spec/services/releaf/content/node/copy_spec.rb +115 -0
  40. data/spec/services/releaf/content/node/move_spec.rb +20 -0
  41. data/spec/services/releaf/content/node/save_under_parent_spec.rb +49 -0
  42. data/spec/services/releaf/content/node/service_spec.rb +19 -0
  43. metadata +38 -21
  44. data/app/builders/releaf/content/go_to_dialog_builder.rb +0 -9
  45. data/app/views/releaf/content/nodes/go_to_dialog.ruby +0 -1
  46. data/lib/releaf/content/builders_autoload.rb +0 -18
  47. data/releaf-content.gemspec +0 -20
@@ -35,23 +35,15 @@ describe ActsAsNode do
35
35
  end
36
36
  end
37
37
 
38
- describe "#node" do
39
- it "returns corresponding node object" do
40
- allow_any_instance_of(Releaf::Content::Node::RootValidator).to receive(:validate)
41
- node = create(:node, content_type: "Book", content_attributes: {title: "xx"})
42
- expect(Book.last.node).to eq(node)
43
- end
44
- end
45
-
46
38
  context ".acts_as_node_params" do
47
39
  before do
48
- allow_any_instance_of(Releaf::Core::ResourceParams).to receive(:values).and_return(["a", "b"])
40
+ allow_any_instance_of(Releaf::ResourceParams).to receive(:values).and_return(["a", "b"])
49
41
  end
50
42
 
51
43
  context "when `params` configuration is nil" do
52
44
  it "returns model params with `id` param" do
53
45
  allow(Book).to receive(:acts_as_node_configuration).and_return(params: nil)
54
- expect(Releaf::Core::ResourceParams).to receive(:new).with(Book).and_call_original
46
+ expect(Releaf::ResourceParams).to receive(:new).with(Book).and_call_original
55
47
  expect(Book.acts_as_node_params).to eq(["a", "b", :id])
56
48
  end
57
49
  end
@@ -66,13 +58,13 @@ describe ActsAsNode do
66
58
 
67
59
  context ".acts_as_node_fields" do
68
60
  before do
69
- allow_any_instance_of(Releaf::Core::ResourceFields).to receive(:values).and_return(["a", "b"])
61
+ allow_any_instance_of(Releaf::ResourceFields).to receive(:values).and_return(["a", "b"])
70
62
  end
71
63
 
72
64
  context "when `fields` configuration is nil" do
73
65
  it "returns model fields" do
74
66
  allow(Book).to receive(:acts_as_node_configuration).and_return(fields: nil)
75
- expect(Releaf::Core::ResourceFields).to receive(:new).with(Book).and_call_original
67
+ expect(Releaf::ResourceFields).to receive(:new).with(Book).and_call_original
76
68
  expect(Book.acts_as_node_fields).to eq(["a", "b"])
77
69
  end
78
70
  end
@@ -85,16 +77,6 @@ describe ActsAsNode do
85
77
  end
86
78
  end
87
79
 
88
- context ".nodes" do
89
- it "loads tree nodes" do
90
- expect(Node).to receive(:where).with(content_type: Book.name)
91
- Book.nodes
92
- end
93
-
94
- it "returns relation" do
95
- expect(Book.nodes.class).to eq(Node::ActiveRecord_Relation)
96
- end
97
- end
98
80
  end
99
81
 
100
82
  describe ActionController::Acts::Node do
@@ -104,15 +86,5 @@ describe ActsAsNode do
104
86
  end
105
87
  end
106
88
 
107
- context ".nodes" do
108
- it "loads tree nodes" do
109
- expect(Node).to receive(:where).with(content_type: ContactFormController.name)
110
- ContactFormController.nodes
111
- end
112
-
113
- it "returns array" do
114
- expect(ContactFormController.nodes.class).to eq(Node::ActiveRecord_Relation)
115
- end
116
- end
117
89
  end
118
90
  end
@@ -0,0 +1,159 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::Content::Configuration do
4
+ class ContentConfigurationDummyNode; end;
5
+ class ContentConfigurationDummyNodesController; end;
6
+ subject{ described_class.new(resources: {}) }
7
+
8
+ describe "#verify_resources_config" do
9
+ context "when valid config" do
10
+ it "does no raise an error" do
11
+ config = {'Node' => { controller: 'Releaf::Content::NodesController'}}
12
+ expect{ subject.verify_resources_config(config) }.to_not raise_error
13
+ end
14
+ end
15
+
16
+ context "when config is not a hash" do
17
+ it "raises an error" do
18
+ config = :foo
19
+ expect{ subject.verify_resources_config(config) }.to raise_error Releaf::Error, "Releaf.application.config.content.resources must be a Hash"
20
+ end
21
+ end
22
+
23
+ context "when any of the hash keys are not strings" do
24
+ it "raises an error" do
25
+ config = {Node => { controller: 'Releaf::Content::NodesController', foo: "wat"}}
26
+ expect{ subject.verify_resources_config(config) }.to raise_error Releaf::Error, "Releaf.application.config.content.resources must have string keys"
27
+ end
28
+ end
29
+
30
+ context "when any of the entries does not have a hash as a value" do
31
+ it "raises an error" do
32
+ config = {'Node' => :foo}
33
+ expect{ subject.verify_resources_config(config) }.to raise_error Releaf::Error, "Node in Releaf.application.config.content.resources must have a hash value"
34
+ end
35
+ end
36
+
37
+ context "when any of the entries does not have controller class name set" do
38
+ it "raises an error" do
39
+ config = {'Node' => { foo: "wat" }}
40
+ expect{ subject.verify_resources_config(config) }.to raise_error Releaf::Error, "Node in Releaf.application.config.content.resources must have controller class specified as a string"
41
+ end
42
+ end
43
+
44
+ context "when any of the entries does not have a string for the controller class name" do
45
+ it "raises an error" do
46
+ config = {'Node' => { controller: Releaf::Content::NodesController, foo: "wat" }}
47
+ expect{ subject.verify_resources_config(config) }.to raise_error Releaf::Error, "Node in Releaf.application.config.content.resources must have controller class specified as a string"
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "#models" do
53
+ it "returns an array of node model classes" do
54
+ expect(subject).to receive(:model_names).and_return(['ContentConfigurationDummyNode', 'Object'])
55
+ expect(subject.models).to eq [ContentConfigurationDummyNode, Object]
56
+ end
57
+ end
58
+
59
+ describe "#model_names" do
60
+ it "returns an array of defined node class names" do
61
+ expect(subject).to receive(:resources).and_return(
62
+ 'ContentConfigurationDummyNode' => { controller: 'Releaf::Content::NodesController' }
63
+ )
64
+ expect(subject.model_names).to eq [ 'ContentConfigurationDummyNode' ]
65
+ end
66
+
67
+ it "caches the result" do
68
+ expect(subject).to receive(:resources).once.and_call_original
69
+ subject.model_names
70
+ subject.model_names
71
+ end
72
+ end
73
+
74
+ describe "#default_model" do
75
+ it "returns the first model from #models" do
76
+ expect(subject).to receive(:models).and_return [ :foo, :bar ]
77
+ expect(subject.default_model).to eq :foo
78
+ end
79
+ end
80
+
81
+ describe "#controllers" do
82
+ it "returns an array of node controller classes" do
83
+ expect(subject).to receive(:controller_names).and_return([
84
+ 'Releaf::Content::NodesController', 'Admin::OtherSite::OtherNodesController'
85
+ ])
86
+ expect(subject.controllers).to eq [Releaf::Content::NodesController, Admin::OtherSite::OtherNodesController]
87
+ end
88
+ end
89
+
90
+ describe "#controller_names" do
91
+ it "returns an array of defined node controller class names" do
92
+ allow(subject).to receive(:resources).and_return(
93
+ 'Node' => { controller: 'Releaf::Content::NodesController' },
94
+ 'ContentConfigurationDummyNode' => { controller: 'ContentConfigurationDummyNodesController' }
95
+ )
96
+ expect(subject.controller_names).to eq [ 'Releaf::Content::NodesController', 'ContentConfigurationDummyNodesController' ]
97
+ end
98
+
99
+ it "caches the result" do
100
+ expect(subject).to receive(:resources).once.and_call_original
101
+ subject.controller_names
102
+ subject.controller_names
103
+ end
104
+ end
105
+
106
+ describe ".routing" do
107
+ it "returns a hash with all node class names as string keys" do
108
+ allow(subject).to receive(:resources).and_return(
109
+ 'Node' => { controller: 'Releaf::Content::NodesController' },
110
+ 'ContentConfigurationDummyNode' => { controller: 'ContentConfigurationDummyNodesController' }
111
+ )
112
+ result = subject.routing
113
+ expect( result ).to be_a Hash
114
+ expect( result.keys ).to eq ['Node', 'ContentConfigurationDummyNode' ]
115
+ end
116
+
117
+ context "when node has no routing defined" do
118
+ it "returns routing hash with site and constraints set to nil" do
119
+ allow(subject).to receive(:resources).and_return(
120
+ 'Node' => { controller: 'Releaf::Content::NodesController' }
121
+ )
122
+ expect(subject.routing).to eq 'Node' => { site: nil, constraints: nil }
123
+ end
124
+ end
125
+
126
+ context "when node has nil values for site and constraints in routing config" do
127
+ it "returns routing hash with site and constraints set to nil" do
128
+ allow(subject).to receive(:resources).and_return(
129
+ 'Node' => {controller: 'Releaf::Content::NodesController', routing: { site: nil, constraints: nil }}
130
+ )
131
+ expect(subject.routing).to eq 'Node' => { site: nil, constraints: nil }
132
+ end
133
+ end
134
+
135
+ context "when node has site defined in routing config" do
136
+ it "returns the defined value in routing hash" do
137
+ allow(subject).to receive(:resources).and_return(
138
+ 'Node' => {controller: 'Releaf::Content::NodesController', routing: { site: "foo" }}
139
+ )
140
+ expect(subject.routing).to eq 'Node' => { site: "foo", constraints: nil }
141
+ end
142
+ end
143
+
144
+ context "when node has constraints defined in routing config" do
145
+ it "returns the defined value in routing hash" do
146
+ allow(subject).to receive(:resources).and_return(
147
+ 'Node' => {controller: 'Releaf::Content::NodesController', routing: { constraints: { host: /foo/ }}}
148
+ )
149
+ expect(subject.routing).to eq 'Node' => { site: nil, constraints: { host: /foo/ } }
150
+ end
151
+ end
152
+
153
+ it "caches the result" do
154
+ expect(subject).to receive(:resources).once.and_call_original
155
+ subject.routing
156
+ subject.routing
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,149 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::Content do
4
+ let(:configuration){ Releaf::Content::Configuration.new(resources: {}) }
5
+
6
+ describe ".configure_component" do
7
+ it "adds new `Releaf::Content::Configuration` configuration with default resources" do
8
+ allow(Releaf::Content::Configuration).to receive(:new)
9
+ .with(resources: { 'Node' => { controller: 'Releaf::Content::NodesController' } }).and_return("_new")
10
+ expect(Releaf.application.config).to receive(:add_configuration).with("_new")
11
+ described_class.configure_component
12
+ end
13
+ end
14
+
15
+ describe ".configuration" do
16
+ it "returns a configuration instance" do
17
+ expect(Releaf.application.config).to receive(:content).and_return(:ok)
18
+ expect(described_class.configuration).to eq :ok
19
+ end
20
+ end
21
+
22
+ [ :resources, :models, :default_model, :controllers, :routing ].each do |method|
23
+ describe ".#{method}" do
24
+ it "returns the method result from the configuration instance" do
25
+ allow(described_class).to receive(:configuration).and_return(configuration)
26
+ allow(configuration).to receive(method).and_return(:ok)
27
+ expect(described_class.send(method)).to eq :ok
28
+ end
29
+ end
30
+ end
31
+
32
+ describe ".draw_component_routes", type: :routing do
33
+ before do
34
+ allow(described_class).to receive(:configuration).and_return(configuration)
35
+ allow(configuration).to receive(:resources).and_return(
36
+ 'Node' => { controller: 'Releaf::Content::NodesController' },
37
+ 'OtherSite::OtherNode' => { controller: 'Admin::OtherSite::OtherNodesController' }
38
+ )
39
+ Dummy::Application.reload_routes!
40
+ end
41
+
42
+ after(:all) do
43
+ Dummy::Application.reload_routes!
44
+ end
45
+
46
+ context "draws named admin routes for all defined content node controllers" do
47
+
48
+ it "draws #index route" do
49
+ expect( releaf_content_nodes_path ).to eq "/admin/nodes"
50
+ expect( admin_other_site_other_nodes_path ).to eq "/admin/other_nodes"
51
+ expect(get: "/admin/nodes").to route_to("releaf/content/nodes#index")
52
+ expect(get: "/admin/other_nodes").to route_to("admin/other_site/other_nodes#index")
53
+ end
54
+
55
+ it "draws #new route" do
56
+ expect( new_releaf_content_node_path ).to eq "/admin/nodes/new"
57
+ expect( new_admin_other_site_other_node_path ).to eq "/admin/other_nodes/new"
58
+ expect(get: "/admin/nodes/new").to route_to("releaf/content/nodes#new")
59
+ expect(get: "/admin/other_nodes/new").to route_to("admin/other_site/other_nodes#new")
60
+ end
61
+
62
+ it "draws #create route" do
63
+ expect(post: "/admin/nodes").to route_to("releaf/content/nodes#create")
64
+ expect(post: "/admin/other_nodes").to route_to("admin/other_site/other_nodes#create")
65
+ end
66
+
67
+ it "draws #content_type_dialog route" do
68
+ expect( content_type_dialog_releaf_content_nodes_path ).to eq "/admin/nodes/content_type_dialog"
69
+ expect( content_type_dialog_admin_other_site_other_nodes_path ).to eq "/admin/other_nodes/content_type_dialog"
70
+ expect(get: "/admin/nodes/content_type_dialog").to route_to("releaf/content/nodes#content_type_dialog")
71
+ expect(get: "/admin/other_nodes/content_type_dialog").to route_to("admin/other_site/other_nodes#content_type_dialog")
72
+ end
73
+
74
+ it "draws #generate_url route" do
75
+ expect( generate_url_releaf_content_nodes_path ).to eq "/admin/nodes/generate_url"
76
+ expect( generate_url_admin_other_site_other_nodes_path ).to eq "/admin/other_nodes/generate_url"
77
+ expect(get: "/admin/nodes/generate_url").to route_to("releaf/content/nodes#generate_url")
78
+ expect(get: "/admin/other_nodes/generate_url").to route_to("admin/other_site/other_nodes#generate_url")
79
+ end
80
+
81
+ it "draws #edit route" do
82
+ expect( edit_releaf_content_node_path(1) ).to eq "/admin/nodes/1/edit"
83
+ expect( edit_admin_other_site_other_node_path(1) ).to eq "/admin/other_nodes/1/edit"
84
+ expect(get: "/admin/nodes/1/edit").to route_to("releaf/content/nodes#edit", "id" => "1")
85
+ expect(get: "/admin/other_nodes/1/edit").to route_to("admin/other_site/other_nodes#edit", "id" => "1")
86
+ end
87
+
88
+ it "draws #update route" do
89
+ expect(patch: "/admin/nodes/1").to route_to("releaf/content/nodes#update", "id" => "1")
90
+ expect(patch: "/admin/other_nodes/1").to route_to("admin/other_site/other_nodes#update", "id" => "1")
91
+ end
92
+
93
+ it "draws #copy_dialog route" do
94
+ expect( copy_dialog_releaf_content_node_path(1) ).to eq "/admin/nodes/1/copy_dialog"
95
+ expect( copy_dialog_admin_other_site_other_node_path(1) ).to eq "/admin/other_nodes/1/copy_dialog"
96
+ expect(get: "/admin/nodes/1/copy_dialog").to route_to("releaf/content/nodes#copy_dialog", "id" => "1")
97
+ expect(get: "/admin/other_nodes/1/copy_dialog").to route_to("admin/other_site/other_nodes#copy_dialog", "id" => "1")
98
+ end
99
+
100
+ it "draws #copy route" do
101
+ expect( copy_releaf_content_node_path(1) ).to eq "/admin/nodes/1/copy"
102
+ expect( copy_admin_other_site_other_node_path(1) ).to eq "/admin/other_nodes/1/copy"
103
+ expect(post: "/admin/nodes/1/copy").to route_to("releaf/content/nodes#copy", "id" => "1")
104
+ expect(post: "/admin/other_nodes/1/copy").to route_to("admin/other_site/other_nodes#copy", "id" => "1")
105
+ end
106
+
107
+ it "draws #move_dialog route" do
108
+ expect( move_dialog_releaf_content_node_path(1) ).to eq "/admin/nodes/1/move_dialog"
109
+ expect( move_dialog_admin_other_site_other_node_path(1) ).to eq "/admin/other_nodes/1/move_dialog"
110
+ expect(get: "/admin/nodes/1/move_dialog").to route_to("releaf/content/nodes#move_dialog", "id" => "1")
111
+ expect(get: "/admin/other_nodes/1/move_dialog").to route_to("admin/other_site/other_nodes#move_dialog", "id" => "1")
112
+ end
113
+
114
+ it "draws #move route" do
115
+ expect( move_releaf_content_node_path(1) ).to eq "/admin/nodes/1/move"
116
+ expect( move_admin_other_site_other_node_path(1) ).to eq "/admin/other_nodes/1/move"
117
+ expect(post: "/admin/nodes/1/move").to route_to("releaf/content/nodes#move", "id" => "1")
118
+ expect(post: "/admin/other_nodes/1/move").to route_to("admin/other_site/other_nodes#move", "id" => "1")
119
+ end
120
+
121
+ it "draws #toolbox route" do
122
+ expect( toolbox_releaf_content_node_path(1) ).to eq "/admin/nodes/1/toolbox"
123
+ expect( toolbox_admin_other_site_other_node_path(1) ).to eq "/admin/other_nodes/1/toolbox"
124
+ expect(get: "/admin/nodes/1/toolbox").to route_to("releaf/content/nodes#toolbox", "id" => "1")
125
+ expect(get: "/admin/other_nodes/1/toolbox").to route_to("admin/other_site/other_nodes#toolbox", "id" => "1")
126
+ end
127
+
128
+ it "draws #confirm_destroy route" do
129
+ expect( confirm_destroy_releaf_content_node_path(1) ).to eq "/admin/nodes/1/confirm_destroy"
130
+ expect( confirm_destroy_admin_other_site_other_node_path(1) ).to eq "/admin/other_nodes/1/confirm_destroy"
131
+ expect(get: "/admin/nodes/1/confirm_destroy").to route_to("releaf/content/nodes#confirm_destroy", "id" => "1")
132
+ expect(get: "/admin/other_nodes/1/confirm_destroy").to route_to("admin/other_site/other_nodes#confirm_destroy", "id" => "1")
133
+ end
134
+
135
+ it "draws #destroy route" do
136
+ expect(delete: "/admin/nodes/1").to route_to("releaf/content/nodes#destroy", "id" => "1")
137
+ expect(delete: "/admin/other_nodes/1").to route_to("admin/other_site/other_nodes#destroy", "id" => "1")
138
+ end
139
+
140
+ it "does not draw #show route" do
141
+ expect(get: "/admin/nodes/1").to route_to("releaf/errors#page_not_found", "path" => "nodes/1")
142
+ expect(get: "/admin/other_nodes/1").to route_to("releaf/errors#page_not_found", "path" => "other_nodes/1")
143
+ end
144
+
145
+ end
146
+
147
+ end
148
+
149
+ end
@@ -42,14 +42,14 @@ describe Node do
42
42
  context 'when #content_type is nil' do
43
43
  it 'returns nil' do
44
44
  subject.content_type = nil
45
- expect( subject.content_class ).to be_nil
45
+ expect( subject.content_class ).to be nil
46
46
  end
47
47
  end
48
48
 
49
49
  context "when #content_type is blank string" do
50
50
  it 'returns nil' do
51
51
  subject.content_type = ""
52
- expect( subject.content_class ).to be_nil
52
+ expect( subject.content_class ).to be nil
53
53
  end
54
54
  end
55
55
 
@@ -121,8 +121,15 @@ describe Node do
121
121
 
122
122
  describe "#attributes_to_not_copy" do
123
123
  it "returns array with attributes" do
124
+ subject.locale = "lv"
124
125
  expect( subject.attributes_to_not_copy ).to match_array %w[content_id depth id item_position lft rgt slug created_at updated_at]
125
126
  end
127
+
128
+ context "when locale is blank" do
129
+ it "includes locale within returned list" do
130
+ expect( subject.attributes_to_not_copy ).to match_array %w[content_id depth id item_position lft rgt slug created_at updated_at locale]
131
+ end
132
+ end
126
133
  end
127
134
 
128
135
  describe "#attributes_to_copy" do
@@ -142,76 +149,7 @@ describe Node do
142
149
  end
143
150
  end
144
151
 
145
- describe "#save_under" do
146
- let(:node1) { create(:node) }
147
-
148
- it "saves node nuder node with given node_id" do
149
- node2 = create(:text_page_node, parent: node1)
150
-
151
- new_node = FactoryGirl.build(:text_page_node)
152
- new_node.send(:save_under, node2.id)
153
- expect( new_node ).to_not be_new_record
154
- expect( new_node.parent ).to eq node2
155
- end
156
-
157
- it "maintains node name, updates slug and then saves record" do
158
- new_node = FactoryGirl.build(:text_page_node)
159
- expect( new_node ).to receive(:maintain_name).ordered.and_call_original
160
- expect( new_node ).to receive(:reasign_slug).ordered.and_call_original
161
- expect( new_node ).to receive(:save!).ordered.and_call_original
162
- new_node.save_under(node1.id)
163
- end
164
-
165
- context "when #validate_root_locale_uniqueness? returns true" do
166
- it "sets locale to nil" do
167
- new_node = FactoryGirl.build(:node)
168
- allow(new_node).to receive(:validate_root_locale_uniqueness?).and_return(true)
169
- new_node.locale = 'xx'
170
- expect { new_node.save_under(nil) }.to change { new_node.locale }.from('xx').to(nil)
171
- end
172
- end
173
-
174
- context "when #validate_root_locale_uniqueness? returns false" do
175
- it "doesn't set locale to nil" do
176
- new_node = FactoryGirl.build(:node)
177
- allow(new_node).to receive(:validate_root_locale_uniqueness?).and_return(false)
178
- new_node.locale = 'xx'
179
- expect { new_node.save_under(nil) }.to_not change { new_node.locale }.from('xx')
180
- end
181
- end
182
-
183
- end
184
-
185
-
186
- describe "#duplicate_content" do
187
-
188
- context "when #content_id is blank" do
189
- let(:node) { create(:node) }
190
-
191
- it "returns nil" do
192
- expect( node.duplicate_content ).to be_nil
193
- end
194
- end
195
-
196
- context "when #content_id is not blank" do
197
- let(:node) { create(:home_page_node) }
198
-
199
- it "returns saved duplicated content" do
200
- content = double('new content')
201
- expect( content ).to receive(:save!)
202
- expect( node ).to receive_message_chain(:content, :dup).and_return(content)
203
- expect( node.duplicate_content ).to eq content
204
- end
205
-
206
- it "doesn't return same as original content" do
207
- result = node.duplicate_content
208
- expect( result ).to be_an_instance_of HomePage
209
- expect( result.id ).to_not eq node.content_id
210
- end
211
- end
212
- end
213
-
214
- describe "#copy_attributes_from" do
152
+ describe "#assign_attributes_from" do
215
153
  let(:source_node) { create(:node, active: false) }
216
154
 
217
155
  it "copies #attributes_to_copy attributes" do
@@ -225,181 +163,11 @@ describe Node do
225
163
 
226
164
  new_node = Node.new
227
165
 
228
- new_node.copy_attributes_from source_node
229
-
230
- expect( new_node.parent_id ).to be_nil
231
- expect( new_node.content_type ).to be_nil
232
- expect( new_node.active ).to be_truthy
233
- end
234
- end
235
-
236
- describe "#duplicate_under!" do
237
- let!(:source_node) { create(:node, locale: "lv") }
238
- let!(:target_node) { create(:node, locale: "en") }
239
-
240
- before do
241
- allow_any_instance_of(Releaf::Content::Node::RootValidator).to receive(:validate)
242
- end
243
-
244
- it "creates duplicated node under target node" do
245
- new_node = Node.new
246
- duplicated_content = double('content', id: 1234)
247
- expect( Node ).to receive(:new).ordered.and_return(new_node)
248
- expect( new_node ).to receive(:copy_attributes_from).with(source_node).ordered.and_call_original
249
- expect( source_node ).to receive(:duplicate_content).ordered.and_return(duplicated_content)
250
- expect( new_node ).to receive(:content_id=).with(1234).ordered
251
- expect( new_node ).to receive(:save_under).with(target_node.id).ordered.and_call_original
252
- source_node.duplicate_under!(target_node.id)
253
- end
166
+ new_node.assign_attributes_from source_node
254
167
 
255
- it "doesn't update settings timestamp" do
256
- expect( Node ).to_not receive(:updated)
257
- source_node.duplicate_under!(target_node.id)
258
- end
259
- end
260
-
261
- describe "#copy", create_nodes: true do
262
- before create_nodes: true do
263
- @home_page_node = create(:home_page_node, locale: "lv")
264
- @home_page_node_2 = create(:home_page_node, locale: "en")
265
- @text_page_node_3 = create(:text_page_node, parent_id: @home_page_node_2.id)
266
- @text_page_node_4 = create(:text_page_node, parent_id: @text_page_node_3.id)
267
- @text_page_node_5 = create(:text_page_node, parent_id: @text_page_node_4.id)
268
-
269
- # it is important to reload nodes, otherwise associations will return empty set
270
- @home_page_node.reload
271
- @home_page_node_2.reload
272
- @text_page_node_3.reload
273
- @text_page_node_4.reload
274
- end
275
-
276
- context "when one of children becomes invalid" do
277
- before do
278
- @text_page_node_4.name = nil
279
- @text_page_node_4.save(validate: false)
280
- end
281
-
282
- it "raises ActiveRecord::RecordInvalid" do
283
- expect { @text_page_node_3.copy(@home_page_node.id) }.to raise_error ActiveRecord::RecordInvalid
284
- end
285
-
286
- it "raises error on node being copied" do
287
- begin
288
- @text_page_node_3.copy(@home_page_node.id)
289
- rescue ActiveRecord::RecordInvalid => e
290
- expect( e.record ).to eq @text_page_node_3
291
- end
292
- expect(@text_page_node_3.errors.messages).to eq(base: ["descendant invalid"])
293
- end
294
-
295
- it "doesn't create any new nodes" do
296
- expect do
297
- begin
298
- @text_page_node_3.copy(@home_page_node.id)
299
- rescue ActiveRecord::RecordInvalid
300
- end
301
- end.to_not change { Node.count }
302
- end
303
-
304
- it "doesn't update settings timestamp" do
305
- expect( Node ).to_not receive(:updated)
306
- begin
307
- @text_page_node_3.copy(@home_page_node.id)
308
- rescue ActiveRecord::RecordInvalid
309
- end
310
- end
311
-
312
- end
313
-
314
-
315
- context "with corect parent_id" do
316
- it "creates node along with descendant nodes" do
317
- expect{ @text_page_node_3.copy(@home_page_node.id) }.to change{ Node.count }.by( @text_page_node_3.descendants.size + 1 )
318
- end
319
-
320
- it "correctly copies attributes" do
321
- allow( @text_page_node_3 ).to receive(:children).and_return([@text_page_node_4])
322
- allow( @text_page_node_4 ).to receive(:children).and_return([@text_page_node_5])
323
-
324
- @text_page_node_3.update_attribute(:active, false)
325
- @text_page_node_4.update_attribute(:active, false)
326
-
327
- allow( @text_page_node_3 ).to receive(:attributes_to_copy).and_return(["name", "parent_id", "content_type"])
328
-
329
- expect( @text_page_node_3 ).to receive(:duplicate_under!).and_call_original.ordered
330
- expect( @text_page_node_4 ).to receive(:duplicate_under!).and_call_original.ordered
331
- expect( @text_page_node_5 ).to receive(:duplicate_under!).and_call_original.ordered
332
-
333
- @text_page_node_3.copy(@home_page_node.id)
334
-
335
- @node_2_copy = @home_page_node.children.first
336
- @node_3_copy = @node_2_copy.children.first
337
- @node_4_copy = @node_3_copy.children.first
338
-
339
- # new nodes by default are active, however we stubbed
340
- # #attributes_to_copy of @test_node_2 to not return active attribute
341
- # Also we updated @test_node_2#active to be false.
342
- # However copy is active, because active attribute wasn't copied
343
- expect( @node_2_copy ).to be_active
344
- # for copy of @text_page_node_3 active attribute was copied however, as it
345
- # should have been
346
- expect( @node_3_copy ).to_not be_active
347
- expect( @node_4_copy ).to be_active
348
-
349
- expect( @node_2_copy.name ).to eq @text_page_node_3.name
350
- expect( @node_3_copy.name ).to eq @text_page_node_4.name
351
- expect( @node_4_copy.name ).to eq @text_page_node_5.name
352
- end
353
-
354
- it "updates settings timestamp only once" do
355
- expect( Node ).to receive(:updated).once.and_call_original
356
- @text_page_node_3.copy(@home_page_node.id)
357
- end
358
-
359
- context "when parent_id is nil" do
360
- it "creates new node" do
361
- allow_any_instance_of(Releaf::Content::Node::RootValidator).to receive(:validate)
362
- expect{ @text_page_node_3.copy(nil) }.to change{ Node.count }.by(3)
363
- end
364
- end
365
-
366
- context "when copying root nodes", create_nodes: false do
367
- context "when root locale uniqueness is validated" do
368
- it "resets locale to nil" do
369
- @text_page_node = create(:home_page_node, locale: 'en')
370
- allow_any_instance_of(Node).to receive(:validate_root_locale_uniqueness?).and_return(true)
371
- @text_page_node.copy(nil)
372
- expect( Node.last.locale ).to eq nil
373
- end
374
- end
375
-
376
- context "when root locale uniqueness is not validated" do
377
- it "doesn't reset locale to nil" do
378
- @text_page_node = create(:home_page_node, locale: 'en')
379
- allow_any_instance_of(Node).to receive(:validate_root_locale_uniqueness?).and_return(false)
380
- @text_page_node.copy(nil)
381
- expect( Node.last.locale ).to eq 'en'
382
- end
383
- end
384
- end
385
- end
386
-
387
- context "with nonexistent parent_id" do
388
- it "raises ActiveRecord::RecordInvalid" do
389
- expect { @text_page_node_3.copy(99991) }.to raise_error(ActiveRecord::RecordInvalid)
390
- end
391
- end
392
-
393
- context "with same parent_id as node.id" do
394
- it "raises ActiveRecord::RecordInvalid" do
395
- expect{ @text_page_node_3.copy(@text_page_node_3.id) }.to raise_error(ActiveRecord::RecordInvalid)
396
- end
397
- end
398
-
399
- context "when copying to child node" do
400
- it "raises ActiveRecord::RecordInvalid" do
401
- expect{ @text_page_node_3.copy(@text_page_node_4.id) }.to raise_error(ActiveRecord::RecordInvalid)
402
- end
168
+ expect( new_node.parent_id ).to be nil
169
+ expect( new_node.content_type ).to be nil
170
+ expect( new_node.active ).to be true
403
171
  end
404
172
  end
405
173
 
@@ -437,66 +205,10 @@ describe Node do
437
205
  end
438
206
 
439
207
  describe "#move" do
440
- before do
441
- @home_page_node = create(:home_page_node, locale: "lv")
442
- @home_page_node_2 = create(:home_page_node, locale: "en")
443
- @text_page_node_3 = create(:text_page_node, parent_id: @home_page_node_2.id)
444
- @text_page_node_4 = create(:text_page_node, parent_id: @text_page_node_3.id)
445
-
446
- # it is important to reload nodes, otherwise associations will return empty set
447
- @home_page_node.reload
448
- @home_page_node_2.reload
449
- @text_page_node_3.reload
450
- @text_page_node_4.reload
208
+ it "calls Node move service" do
209
+ expect(Releaf::Content::Node::Move).to receive(:call).with(node: subject, parent_id: 12)
210
+ subject.move(12)
451
211
  end
452
-
453
- context "when one of children becomes invalid" do
454
- before do
455
- @text_page_node_4.name = nil
456
- @text_page_node_4.save(validate: false)
457
- end
458
-
459
- it "raises ActiveRecord::RecordInvalid" do
460
- expect { @text_page_node_3.move(@home_page_node.id) }.to raise_error ActiveRecord::RecordInvalid
461
- end
462
-
463
- it "raises error on node being moved, even tought descendant has error" do
464
- begin
465
- @text_page_node_3.move(@home_page_node.id)
466
- rescue ActiveRecord::RecordInvalid => e
467
- expect( e.record ).to eq @text_page_node_3
468
- end
469
-
470
- expect(@text_page_node_3.errors.messages).to eq(name: [], base: ["descendant invalid"])
471
- end
472
- end
473
-
474
- context "when moving existing node to other nodes child's position" do
475
- it "changes parent_id" do
476
- 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)
477
- end
478
- end
479
-
480
- context "when moving to self child's position" do
481
- it "raises ActiveRecord::RecordInvalid" do
482
- expect{ @text_page_node_3.move(@text_page_node_3.id) }.to raise_error(ActiveRecord::RecordInvalid)
483
- end
484
- end
485
-
486
- context "when passing nil as target node" do
487
- it "updates parent_id" do
488
- allow_any_instance_of(Releaf::Content::Node::RootValidator).to receive(:validate)
489
- @home_page_node.destroy
490
- expect{ @text_page_node_3.move(nil) }.to change { Node.find(@text_page_node_3.id).parent_id }.to(nil)
491
- end
492
- end
493
-
494
- context "when passing nonexistent target node's id" do
495
- it "raises ActiveRecord::RecordInvalid" do
496
- expect{ @text_page_node_3.move(998123) }.to raise_error(ActiveRecord::RecordInvalid)
497
- end
498
- end
499
-
500
212
  end
501
213
 
502
214
  describe "#maintain_name" do
@@ -719,20 +431,6 @@ describe Node do
719
431
  end
720
432
  end
721
433
 
722
- describe "#add_error_and_raise" do
723
- it "raises error" do
724
- expect { subject.add_error_and_raise('test error') }.to raise_error(ActiveRecord::RecordInvalid)
725
- end
726
-
727
- it "adds record on base and raise ActiveRecord::RecordInvalid" do
728
- begin
729
- subject.add_error_and_raise('test error')
730
- rescue ActiveRecord::RecordInvalid => e
731
- expect( e.record.errors[:base] ).to include 'test error'
732
- end
733
- end
734
- end
735
-
736
434
  describe "#prevent_auto_update_settings_timestamp" do
737
435
  it "sets #prevent_auto_update_settings_timestamp? to true within block" do
738
436
  expect do
@@ -769,11 +467,55 @@ describe Node do
769
467
  end
770
468
 
771
469
  describe "#path" do
772
- it "returns relative path of node" do
773
- node = described_class.new(slug: 'foo')
774
- node2 = described_class.new(slug: 'bar', parent: node)
775
- expect( node.path ).to eq '/foo'
776
- expect( node2.path ).to eq '/foo/bar'
470
+ before do
471
+ allow(subject).to receive(:path_parts).and_return(["some", "bar", "foo"])
472
+ end
473
+
474
+ it "returns relative node path built ny joining node path parts" do
475
+ expect(subject.path).to eq("/some/bar/foo")
476
+ end
477
+
478
+ context "when node has parent" do
479
+ it "ads trailing slash to returned node path" do
480
+ allow(subject).to receive(:trailing_slash_for_path?).and_return(true)
481
+ expect(subject.path).to eq("/some/bar/foo/")
482
+ end
483
+ end
484
+ end
485
+
486
+
487
+ describe "#trailing_slash_for_path?" do
488
+ context "when rails route has trailing slash enabled" do
489
+ it "returns true" do
490
+ allow(Rails.application.routes).to receive(:default_url_options).and_return(trailing_slash: true)
491
+ expect(subject.trailing_slash_for_path?).to be true
492
+ end
493
+ end
494
+
495
+ context "when rails route has trailing slash disabled" do
496
+ it "returns false" do
497
+ allow(Rails.application.routes).to receive(:default_url_options).and_return({})
498
+ expect(subject.trailing_slash_for_path?).to be false
499
+ end
500
+ end
501
+ end
502
+
503
+ describe "#path_parts" do
504
+ it "returns array with slug" do
505
+ expect(subject.path_parts).to eq([""])
506
+ subject.slug = "foo"
507
+ expect(subject.path_parts).to eq(["foo"])
508
+ end
509
+
510
+ context "when node has parent" do
511
+ it "prepends parent path parts to returned array" do
512
+ parent = described_class.new
513
+ allow(parent).to receive(:path_parts).and_return(%w(some bar))
514
+
515
+ subject.slug = "foo"
516
+ subject.parent = parent
517
+ expect(subject.path_parts).to eq(["some", "bar", "foo"])
518
+ end
777
519
  end
778
520
  end
779
521
  end