dry-view 0.1.1 → 0.2.0

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +15 -11
  3. data/CHANGELOG.md +23 -0
  4. data/Gemfile +6 -5
  5. data/README.md +8 -1
  6. data/benchmarks/templates/{button.erb → button.html.erb} +0 -0
  7. data/benchmarks/view.rb +3 -4
  8. data/bin/console +7 -0
  9. data/dry-view.gemspec +7 -6
  10. data/lib/dry/view/controller.rb +107 -0
  11. data/lib/dry/view/exposure.rb +61 -0
  12. data/lib/dry/view/exposures.rb +50 -0
  13. data/lib/dry/view/path.rb +40 -0
  14. data/lib/dry/view/renderer.rb +20 -28
  15. data/lib/dry/view/scope.rb +55 -0
  16. data/lib/dry/view/version.rb +1 -1
  17. data/lib/dry/view.rb +1 -1
  18. data/spec/fixtures/templates/empty.html.slim +1 -0
  19. data/spec/fixtures/templates/layouts/app.html.slim +1 -1
  20. data/spec/fixtures/templates/layouts/app.txt.erb +1 -1
  21. data/spec/fixtures/templates/parts_with_args/_box.html.slim +3 -0
  22. data/spec/fixtures/templates/parts_with_args.html.slim +3 -0
  23. data/spec/fixtures/templates/users/_tbody.html.slim +1 -1
  24. data/spec/fixtures/templates/users.html.slim +4 -4
  25. data/spec/fixtures/templates/users.txt.erb +0 -2
  26. data/spec/fixtures/templates/users_with_count.html.slim +5 -0
  27. data/spec/fixtures/templates_override/users.html.slim +5 -0
  28. data/spec/integration/exposures_spec.rb +178 -0
  29. data/spec/integration/view_spec.rb +83 -20
  30. data/spec/spec_helper.rb +13 -3
  31. data/spec/unit/controller_spec.rb +36 -0
  32. data/spec/unit/exposure_spec.rb +146 -0
  33. data/spec/unit/exposures_spec.rb +63 -0
  34. data/spec/unit/renderer_spec.rb +2 -1
  35. data/spec/unit/scope_spec.rb +98 -0
  36. metadata +36 -46
  37. data/lib/dry/view/layout.rb +0 -126
  38. data/lib/dry/view/null_part.rb +0 -30
  39. data/lib/dry/view/part.rb +0 -39
  40. data/lib/dry/view/value_part.rb +0 -50
  41. data/spec/unit/layout_spec.rb +0 -55
  42. data/spec/unit/null_part_spec.rb +0 -39
  43. data/spec/unit/value_part_spec.rb +0 -55
@@ -0,0 +1,178 @@
1
+ RSpec.describe 'exposures' do
2
+ let(:context) { Struct.new(:title, :assets).new('dry-view rocks!', -> input { "#{input}.jpg" }) }
3
+
4
+ it 'uses exposures to build view locals' do
5
+ vc = Class.new(Dry::View::Controller) do
6
+ configure do |config|
7
+ config.paths = SPEC_ROOT.join('fixtures/templates')
8
+ config.layout = 'app'
9
+ config.template = 'users'
10
+ config.default_format = :html
11
+ end
12
+
13
+ expose :users do |input|
14
+ input.fetch(:users).map { |user|
15
+ user.merge(name: user[:name].upcase)
16
+ }
17
+ end
18
+ end.new
19
+
20
+ users = [
21
+ { name: 'Jane', email: 'jane@doe.org' },
22
+ { name: 'Joe', email: 'joe@doe.org' }
23
+ ]
24
+
25
+ expect(vc.(users: users, context: context)).to eql(
26
+ '<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>JANE</td><td>jane@doe.org</td></tr><tr><td>JOE</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>'
27
+ )
28
+ end
29
+
30
+ it 'supports both blocks and instance methods as exposures' do
31
+ vc = Class.new(Dry::View::Controller) do
32
+ configure do |config|
33
+ config.paths = SPEC_ROOT.join('fixtures/templates')
34
+ config.layout = 'app'
35
+ config.template = 'users'
36
+ config.default_format = :html
37
+ end
38
+
39
+ expose :users
40
+
41
+ private
42
+
43
+ def users(input)
44
+ input.fetch(:users).map { |user|
45
+ user.merge(name: user[:name].upcase)
46
+ }
47
+ end
48
+ end.new
49
+
50
+ users = [
51
+ { name: 'Jane', email: 'jane@doe.org' },
52
+ { name: 'Joe', email: 'joe@doe.org' }
53
+ ]
54
+
55
+ expect(vc.(users: users, context: context)).to eql(
56
+ '<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>JANE</td><td>jane@doe.org</td></tr><tr><td>JOE</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>'
57
+ )
58
+ end
59
+
60
+ it 'passes matching input data if no proc or instance method is available' do
61
+ vc = Class.new(Dry::View::Controller) do
62
+ configure do |config|
63
+ config.paths = SPEC_ROOT.join('fixtures/templates')
64
+ config.layout = 'app'
65
+ config.template = 'users'
66
+ config.default_format = :html
67
+ end
68
+
69
+ expose :users
70
+ end.new
71
+
72
+ users = [
73
+ { name: 'Jane', email: 'jane@doe.org' },
74
+ { name: 'Joe', email: 'joe@doe.org' }
75
+ ]
76
+
77
+ expect(vc.(users: users, context: context)).to eql(
78
+ '<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>'
79
+ )
80
+ end
81
+
82
+ it 'allows exposures to depend on each other' do
83
+ vc = Class.new(Dry::View::Controller) do
84
+ configure do |config|
85
+ config.paths = SPEC_ROOT.join('fixtures/templates')
86
+ config.layout = 'app'
87
+ config.template = 'users_with_count'
88
+ config.default_format = :html
89
+ end
90
+
91
+ expose :users do |input|
92
+ input.fetch(:users)
93
+ end
94
+
95
+ expose :users_count do |users|
96
+ "#{users.length} users"
97
+ end
98
+ end.new
99
+
100
+ users = [
101
+ {name: 'Jane', email: 'jane@doe.org'},
102
+ {name: 'Joe', email: 'joe@doe.org'}
103
+ ]
104
+
105
+ expect(vc.(users: users, context: context)).to eql(
106
+ '<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">2 users</div></body></html>'
107
+ )
108
+ end
109
+
110
+ it 'supports defining multiple exposures at once' do
111
+ vc = Class.new(Dry::View::Controller) do
112
+ configure do |config|
113
+ config.paths = SPEC_ROOT.join('fixtures/templates')
114
+ config.layout = 'app'
115
+ config.template = 'users_with_count'
116
+ config.default_format = :html
117
+ end
118
+
119
+ expose :users, :users_count
120
+
121
+ private
122
+
123
+ def users(input)
124
+ input.fetch(:users)
125
+ end
126
+
127
+ def users_count(users)
128
+ "#{users.length} users"
129
+ end
130
+ end.new
131
+
132
+ users = [
133
+ {name: 'Jane', email: 'jane@doe.org'},
134
+ {name: 'Joe', email: 'joe@doe.org'}
135
+ ]
136
+
137
+ expect(vc.(users: users, context: context)).to eql(
138
+ '<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">2 users</div></body></html>'
139
+ )
140
+ end
141
+
142
+ it 'allows exposures to be hidden from the view' do
143
+ vc = Class.new(Dry::View::Controller) do
144
+ configure do |config|
145
+ config.paths = SPEC_ROOT.join('fixtures/templates')
146
+ config.layout = 'app'
147
+ config.template = 'users_with_count'
148
+ config.default_format = :html
149
+ end
150
+
151
+ private_expose :prefix do
152
+ "COUNT: "
153
+ end
154
+
155
+ expose :users do |input|
156
+ input.fetch(:users)
157
+ end
158
+
159
+ expose :users_count do |prefix, users|
160
+ "#{prefix}#{users.length} users"
161
+ end
162
+ end.new
163
+
164
+ users = [
165
+ {name: 'Jane', email: 'jane@doe.org'},
166
+ {name: 'Joe', email: 'joe@doe.org'}
167
+ ]
168
+
169
+ input = {users: users, context: context}
170
+
171
+ expect(vc.(input)).to eql(
172
+ '<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><ul><li>Jane (jane@doe.org)</li><li>Joe (joe@doe.org)</li></ul><div class="count">COUNT: 2 users</div></body></html>'
173
+ )
174
+
175
+ expect(vc.locals(input)).to include(:users, :users_count)
176
+ expect(vc.locals(input)).not_to include(:prefix)
177
+ end
178
+ end
@@ -1,51 +1,114 @@
1
1
  RSpec.describe 'dry-view' do
2
- let(:view_class) do
3
- Class.new(Dry::View::Layout) do
2
+ let(:vc_class) do
3
+ Class.new(Dry::View::Controller) do
4
4
  configure do |config|
5
- config.root = SPEC_ROOT.join('fixtures/templates')
6
- config.name = 'app'
5
+ config.paths = SPEC_ROOT.join('fixtures/templates')
6
+ config.layout = 'app'
7
7
  config.template = 'users'
8
- config.formats = {html: :slim, txt: :erb}
8
+ config.default_format = :html
9
9
  end
10
10
  end
11
11
  end
12
12
 
13
- let(:scope) do
14
- Struct.new(:title).new('dry-view rocks!')
13
+ let(:context) do
14
+ Struct.new(:title, :assets).new('dry-view rocks!', -> input { "#{input}.jpg" })
15
15
  end
16
16
 
17
- it 'renders within a layout using provided scope' do
18
- view = view_class.new
17
+ it 'renders within a layout and makes the provided context available everywhere' do
18
+ vc = vc_class.new
19
19
 
20
20
  users = [
21
21
  { name: 'Jane', email: 'jane@doe.org' },
22
22
  { name: 'Joe', email: 'joe@doe.org' }
23
23
  ]
24
24
 
25
- expect(view.(scope: scope, locals: { subtitle: "Users List", users: users })).to eql(
26
- '<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><h2>Users List</h2><div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div></body></html>'
25
+ expect(vc.(context: context, locals: {users: users})).to eql(
26
+ '<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" /></body></html>'
27
+ )
28
+ end
29
+
30
+ it 'renders without a layout' do
31
+ vc = Class.new(vc_class) do
32
+ configure do |config|
33
+ config.layout = false
34
+ end
35
+ end.new
36
+
37
+ users = [
38
+ { name: 'Jane', email: 'jane@doe.org' },
39
+ { name: 'Joe', email: 'joe@doe.org' }
40
+ ]
41
+
42
+ expect(vc.(context: context, locals: {users: users})).to eql(
43
+ '<div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div><img src="mindblown.jpg" />'
44
+ )
45
+ end
46
+
47
+ it 'renders a view without locals' do
48
+ vc = Class.new(vc_class) do
49
+ configure do |config|
50
+ config.template = 'empty'
51
+ end
52
+ end.new
53
+
54
+ expect(vc.(context: context, locals: {})).to eq(
55
+ '<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><p>This is a view with no locals.</p></body></html>'
27
56
  )
28
57
  end
29
58
 
30
59
  it 'renders a view with an alternative format and engine' do
31
- view = view_class.new
60
+ vc = vc_class.new
61
+
62
+ users = [
63
+ { name: 'Jane', email: 'jane@doe.org' },
64
+ { name: 'Joe', email: 'joe@doe.org' }
65
+ ]
66
+
67
+ expect(vc.(context: context, locals: {users: users}, format: 'txt').strip).to eql(
68
+ "# dry-view rocks!\n\n* Jane (jane@doe.org)\n* Joe (joe@doe.org)"
69
+ )
70
+ end
71
+
72
+ it 'renders a view with a template on another view path' do
73
+ vc = Class.new(vc_class) do
74
+ configure do |config|
75
+ config.paths = [SPEC_ROOT.join('fixtures/templates_override')] + Array(config.paths)
76
+ end
77
+ end.new
78
+
79
+ users = [
80
+ { name: 'Jane', email: 'jane@doe.org' },
81
+ { name: 'Joe', email: 'joe@doe.org' }
82
+ ]
83
+
84
+ expect(vc.(context: context, locals: {users: users})).to eq(
85
+ '<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><h1>OVERRIDE</h1><div class="users"><table><tbody><tr><td>Jane</td><td>jane@doe.org</td></tr><tr><td>Joe</td><td>joe@doe.org</td></tr></tbody></table></div></body></html>'
86
+ )
87
+ end
88
+
89
+ it 'renders a view that passes arguments to partials' do
90
+ vc = Class.new(vc_class) do
91
+ configure do |config|
92
+ config.template = 'parts_with_args'
93
+ end
94
+ end.new
32
95
 
33
96
  users = [
34
97
  { name: 'Jane', email: 'jane@doe.org' },
35
98
  { name: 'Joe', email: 'joe@doe.org' }
36
99
  ]
37
100
 
38
- expect(view.(scope: scope, locals: { subtitle: 'Users List', users: users }, format: 'txt').strip).to eql(
39
- "# dry-view rocks!\n\n## Users List\n\n* Jane (jane@doe.org)\n* Joe (joe@doe.org)"
101
+ expect(vc.(context: context, locals: {users: users})).to eq(
102
+ '<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><div class="users"><div class="box"><h2>Nombre</h2>Jane</div><div class="box"><h2>Nombre</h2>Joe</div></div></body></html>'
40
103
  )
41
104
  end
42
105
 
43
106
  describe 'inheritance' do
44
107
  let(:parent_view) do
45
- klass = Class.new(Dry::View::Layout)
108
+ klass = Class.new(Dry::View::Controller)
46
109
 
47
- klass.setting :root, SPEC_ROOT.join('fixtures/templates')
48
- klass.setting :name, 'app'
110
+ klass.setting :paths, SPEC_ROOT.join('fixtures/templates')
111
+ klass.setting :layout, 'app'
49
112
  klass.setting :formats, {html: :slim}
50
113
 
51
114
  klass
@@ -59,10 +122,10 @@ RSpec.describe 'dry-view' do
59
122
  end
60
123
  end
61
124
 
62
- it 'renders within a parent class layout using provided scope' do
63
- view = child_view.new
125
+ it 'renders within a parent class layout using provided context' do
126
+ vc = child_view.new
64
127
 
65
- expect(view.(scope: scope, locals: { tasks: [{ title: 'one' }, { title: 'two' }] })).to eql(
128
+ expect(vc.(context: context, locals: { tasks: [{ title: 'one' }, { title: 'two' }] })).to eql(
66
129
  '<!DOCTYPE html><html><head><title>dry-view rocks!</title></head><body><ol><li>one</li><li>two</li></ol></body></html>'
67
130
  )
68
131
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,8 @@
1
- if RUBY_ENGINE == "rbx"
2
- require "codeclimate-test-reporter"
3
- CodeClimate::TestReporter.start
1
+ if RUBY_ENGINE == 'ruby'
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter "/spec/"
5
+ end
4
6
  end
5
7
 
6
8
  begin
@@ -24,3 +26,11 @@ RSpec.configure do |config|
24
26
  config.order = :random
25
27
  Kernel.srand config.seed
26
28
  end
29
+
30
+ RSpec::Matchers.define :part_including do |data|
31
+ match { |actual|
32
+ data.all? { |(key, val)|
33
+ actual._data[key] == val
34
+ }
35
+ }
36
+ end
@@ -0,0 +1,36 @@
1
+ RSpec.describe Dry::View::Controller do
2
+ subject(:layout) { layout_class.new }
3
+
4
+ let(:layout_class) do
5
+ klass = Class.new(Dry::View::Controller)
6
+
7
+ klass.configure do |config|
8
+ config.paths = SPEC_ROOT.join('fixtures/templates')
9
+ config.layout = 'app'
10
+ config.template = 'user'
11
+ config.default_format = :html
12
+ end
13
+
14
+ klass
15
+ end
16
+
17
+ let(:page) do
18
+ double(:page, title: 'Test')
19
+ end
20
+
21
+ let(:options) do
22
+ { context: page, locals: { user: { name: 'Jane' }, header: { title: 'User' } } }
23
+ end
24
+
25
+ let(:renderer) do
26
+ layout.class.renderers[:html]
27
+ end
28
+
29
+ describe '#call' do
30
+ it 'renders template within the layout' do
31
+ expect(layout.(options)).to eql(
32
+ '<!DOCTYPE html><html><head><title>Test</title></head><body><h1>User</h1><p>Jane</p></body></html>'
33
+ )
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,146 @@
1
+ RSpec.describe Dry::View::Exposure do
2
+ subject(:exposure) { described_class.new(:hello, proc) }
3
+
4
+ let(:proc) { -> input { "hi" } }
5
+
6
+ describe "initialization and attributes" do
7
+ describe "#name" do
8
+ it "accepts a name" do
9
+ expect(exposure.name).to eql :hello
10
+ end
11
+ end
12
+
13
+ describe "#proc" do
14
+ it "accepts a proc" do
15
+ expect(exposure.proc).to eql proc
16
+ end
17
+
18
+ it "allows a nil proc" do
19
+ expect(described_class.new(:hello).proc).to be_nil
20
+ end
21
+
22
+ it "allows proc to take no arguments" do
23
+ proc = -> { "hi" }
24
+ expect { described_class.new(:hello, proc) }.not_to raise_error
25
+ end
26
+
27
+ it "requires proc to take positional arguments only" do
28
+ proc = -> a: "a" { "hi" }
29
+ expect { described_class.new(:hello, proc) }.to raise_error ArgumentError
30
+
31
+ proc = -> input, a: "a" { "hi" }
32
+ expect { described_class.new(:hello, proc) }.to raise_error ArgumentError
33
+ end
34
+ end
35
+
36
+ describe "#to_view" do
37
+ it "is true by default" do
38
+ expect(exposure.to_view).to be true
39
+ end
40
+
41
+ it "can be set to false on initialization" do
42
+ expect(described_class.new(:hello, to_view: false).to_view).to be false
43
+ end
44
+ end
45
+ end
46
+
47
+ describe "#bind" do
48
+ context "proc provided" do
49
+ subject(:bound_exposure) { exposure.bind(Object.new) }
50
+
51
+ it "returns itself" do
52
+ expect(bound_exposure).to eql exposure
53
+ end
54
+
55
+ it "retains the same proc" do
56
+ expect(bound_exposure.proc).to eql proc
57
+ end
58
+ end
59
+
60
+ context "no proc provided" do
61
+ subject(:bound_exposure) { exposure.bind(object) }
62
+
63
+ let(:exposure) { described_class.new(:hello) }
64
+
65
+ context "matching instance method" do
66
+ let(:object) do
67
+ Class.new do
68
+ def hello(input)
69
+ "hi there, #{input.fetch(:name)}"
70
+ end
71
+ end.new
72
+ end
73
+
74
+ it "returns a new object" do
75
+ expect(bound_exposure).not_to eql exposure
76
+ end
77
+
78
+ it "sets the proc to the method on the object matching the exposure's name" do
79
+ expect(bound_exposure.proc).to eql object.method(:hello)
80
+ end
81
+ end
82
+
83
+ context "no matching instance method" do
84
+ let(:object) { Object.new }
85
+
86
+ it "returns a new object" do
87
+ expect(bound_exposure).not_to eql exposure
88
+ end
89
+
90
+ it "builds a proc that passes through data from a matching key in the input" do
91
+ expect(bound_exposure.proc.(hello: "hello in input")).to eq "hello in input"
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "#dependencies" do
98
+ let(:proc) { -> input, foo, bar { "hi" } }
99
+
100
+ it "returns an array of exposure dependencies derived from the proc's argument names" do
101
+ expect(exposure.dependencies).to eql [:input, :foo, :bar]
102
+ end
103
+ end
104
+
105
+ describe "#call" do
106
+ let(:input) { double("input") }
107
+
108
+ before do
109
+ allow(proc).to receive(:call)
110
+ end
111
+
112
+ context "proc expects input only" do
113
+ it "sends the input to the proc" do
114
+ exposure.(input)
115
+
116
+ expect(proc).to have_received(:call).with(input)
117
+ end
118
+ end
119
+
120
+ context "proc expects input and dependencies" do
121
+ let(:proc) { -> input, greeting { "#{greeting}, #{input.fetch(:name)}" } }
122
+ let(:locals) { {greeting: "Hola"} }
123
+
124
+ before do
125
+ exposure.(input, locals)
126
+ end
127
+
128
+ it "sends the input and dependency values to the proc" do
129
+ expect(proc).to have_received(:call).with(input, "Hola")
130
+ end
131
+ end
132
+
133
+ context "proc expects dependencies only" do
134
+ let(:proc) { -> greeting, farewell { "#{greeting}, #{input.fetch(:name)}" } }
135
+ let(:locals) { {greeting: "Hola", farewell: "Adios"} }
136
+
137
+ before do
138
+ exposure.(input, locals)
139
+ end
140
+
141
+ it "sends the dependency values to the proc" do
142
+ expect(proc).to have_received(:call).with "Hola", "Adios"
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,63 @@
1
+ RSpec.describe Dry::View::Exposures do
2
+ subject(:exposures) { described_class.new }
3
+
4
+ describe "#exposures" do
5
+ it "is empty by defalut" do
6
+ expect(exposures.exposures).to be_empty
7
+ end
8
+ end
9
+
10
+ describe "#add" do
11
+ it "creates and adds an exposure" do
12
+ proc = -> input { "hi" }
13
+ exposures.add :hello, proc
14
+
15
+ expect(exposures[:hello].name).to eq :hello
16
+ expect(exposures[:hello].proc).to eq proc
17
+ end
18
+ end
19
+
20
+ describe "#bind" do
21
+ subject(:bound_exposures) { exposures.bind(object) }
22
+
23
+ let(:object) do
24
+ Class.new do
25
+ def hello(input)
26
+ "hi"
27
+ end
28
+ end.new
29
+ end
30
+
31
+ before do
32
+ exposures.add(:hello)
33
+ end
34
+
35
+ it "binds each of the exposures" do
36
+ expect(bound_exposures[:hello].proc).to eq object.method(:hello)
37
+ end
38
+
39
+ it "returns a new copy of the exposures" do
40
+ expect(exposures.exposures).not_to eql(bound_exposures.exposures)
41
+ end
42
+ end
43
+
44
+ describe "#locals" do
45
+ before do
46
+ exposures.add(:greeting, -> input { input.fetch(:greeting).upcase })
47
+ exposures.add(:farewell, -> greeting { "#{greeting} and goodbye" })
48
+ end
49
+
50
+ subject(:locals) { exposures.locals(greeting: "hello") }
51
+
52
+ it "returns the values from the exposures' procs" do
53
+ expect(locals).to eq(greeting: "HELLO", farewell: "HELLO and goodbye")
54
+ end
55
+
56
+ it "does not return any values from private exposures" do
57
+ exposures.add(:hidden, -> input { "shh" }, to_view: false)
58
+
59
+ expect(locals).to include(:greeting, :farewell)
60
+ expect(locals).not_to include(:hidden)
61
+ end
62
+ end
63
+ end
@@ -1,8 +1,9 @@
1
+ require 'dry/view/path'
1
2
  require 'dry/view/renderer'
2
3
 
3
4
  RSpec.describe Dry::View::Renderer do
4
5
  subject(:renderer) do
5
- Dry::View::Renderer.new(SPEC_ROOT.join('fixtures/templates'), format: 'html', engine: :slim)
6
+ Dry::View::Renderer.new([Dry::View::Path.new(SPEC_ROOT.join('fixtures/templates'))], format: 'html')
6
7
  end
7
8
 
8
9
  let(:scope) { double(:scope) }