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.
- checksums.yaml +4 -4
- data/LICENSE +19 -21
- data/app/assets/javascripts/{releaf/controllers → controllers}/releaf/content/nodes.js +0 -0
- data/app/assets/stylesheets/{releaf/controllers → controllers}/releaf/content/nodes.scss +0 -0
- data/app/builders/releaf/content/builders/action_dialog.rb +9 -1
- data/app/builders/releaf/content/builders/tree.rb +1 -1
- data/app/builders/releaf/content/content_type_dialog_builder.rb +2 -2
- data/app/builders/releaf/content/nodes/form_builder.rb +3 -3
- data/app/builders/releaf/content/nodes/index_builder.rb +1 -1
- data/app/builders/releaf/content/nodes/toolbox_builder.rb +0 -5
- data/app/controllers/releaf/content/nodes_controller.rb +109 -129
- data/app/middleware/releaf/content/routes_reloader.rb +12 -4
- data/app/services/releaf/content/node/copy.rb +90 -0
- data/app/services/releaf/content/node/move.rb +21 -0
- data/app/services/releaf/content/node/save_under_parent.rb +22 -0
- data/app/services/releaf/content/node/service.rb +17 -0
- data/app/validators/releaf/content/node/singleness_validator.rb +1 -24
- data/lib/releaf-content.rb +85 -6
- data/lib/releaf/content/acts_as_node.rb +0 -5
- data/lib/releaf/content/acts_as_node/active_record/acts/node.rb +2 -8
- data/lib/releaf/content/configuration.rb +61 -0
- data/lib/releaf/content/engine.rb +1 -34
- data/lib/releaf/content/node.rb +30 -101
- data/lib/releaf/content/node_mapper.rb +28 -2
- data/lib/releaf/content/route.rb +37 -25
- data/spec/builders/content/nodes/action_dialog_spec.rb +39 -0
- data/spec/builders/content/nodes/form_builder_spec.rb +47 -3
- data/spec/builders/content/nodes/toolbox_builder_spec.rb +1 -32
- data/spec/controllers/releaf/content/nodes_controller_spec.rb +42 -11
- data/spec/features/nodes_services_spec.rb +207 -0
- data/spec/features/nodes_spec.rb +328 -30
- data/spec/lib/releaf/content/acts_as_node_spec.rb +4 -32
- data/spec/lib/releaf/content/configuration_spec.rb +159 -0
- data/spec/lib/releaf/content/engine_spec.rb +149 -0
- data/spec/lib/releaf/content/node_spec.rb +66 -324
- data/spec/lib/releaf/content/route_spec.rb +223 -34
- data/spec/middleware/routes_reloader_spec.rb +62 -14
- data/spec/routing/node_mapper_spec.rb +223 -55
- data/spec/services/releaf/content/node/copy_spec.rb +115 -0
- data/spec/services/releaf/content/node/move_spec.rb +20 -0
- data/spec/services/releaf/content/node/save_under_parent_spec.rb +49 -0
- data/spec/services/releaf/content/node/service_spec.rb +19 -0
- metadata +38 -21
- data/app/builders/releaf/content/go_to_dialog_builder.rb +0 -9
- data/app/views/releaf/content/nodes/go_to_dialog.ruby +0 -1
- data/lib/releaf/content/builders_autoload.rb +0 -18
- 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::
|
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::
|
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::
|
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::
|
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
|
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
|
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 "#
|
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.
|
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
|
-
|
256
|
-
expect(
|
257
|
-
|
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
|
-
|
441
|
-
|
442
|
-
|
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
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
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
|