shoes-core 4.0.0.pre3 → 4.0.0.pre4

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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/bin/shoes +1 -1
  3. data/bin/shoes-picker +5 -1
  4. data/bin/shoes-stub +1 -1
  5. data/ext/install/shoes.bat +2 -0
  6. data/lib/rubygems_plugin.rb +2 -2
  7. data/lib/shoes/app.rb +18 -19
  8. data/lib/shoes/arc.rb +8 -8
  9. data/lib/shoes/background.rb +4 -8
  10. data/lib/shoes/border.rb +4 -8
  11. data/lib/shoes/builtin_methods.rb +2 -2
  12. data/lib/shoes/button.rb +2 -9
  13. data/lib/shoes/check_button.rb +0 -12
  14. data/lib/shoes/color.rb +29 -34
  15. data/lib/shoes/common/background_element.rb +4 -0
  16. data/lib/shoes/common/fill.rb +9 -0
  17. data/lib/shoes/common/initialization.rb +59 -0
  18. data/lib/shoes/common/inspect.rb +20 -2
  19. data/lib/shoes/common/rotate.rb +10 -0
  20. data/lib/shoes/common/stroke.rb +9 -0
  21. data/lib/shoes/common/style.rb +21 -7
  22. data/lib/shoes/common/style_normalizer.rb +1 -3
  23. data/lib/shoes/common/ui_element.rb +10 -0
  24. data/lib/shoes/common/visibility.rb +4 -4
  25. data/lib/shoes/configuration.rb +4 -2
  26. data/lib/shoes/core/version.rb +1 -1
  27. data/lib/shoes/dialog.rb +2 -2
  28. data/lib/shoes/dimension.rb +78 -68
  29. data/lib/shoes/dimensions.rb +22 -10
  30. data/lib/shoes/download.rb +26 -10
  31. data/lib/shoes/dsl.rb +32 -51
  32. data/lib/shoes/gradient.rb +6 -13
  33. data/lib/shoes/image.rb +4 -9
  34. data/lib/shoes/input_box.rb +6 -9
  35. data/lib/shoes/internal_app.rb +16 -36
  36. data/lib/shoes/line.rb +29 -10
  37. data/lib/shoes/link.rb +13 -2
  38. data/lib/shoes/list_box.rb +33 -11
  39. data/lib/shoes/logger.rb +12 -13
  40. data/lib/shoes/mock/arc.rb +2 -0
  41. data/lib/shoes/mock/common_methods.rb +9 -0
  42. data/lib/shoes/mock/shape.rb +1 -1
  43. data/lib/shoes/mock/slot.rb +1 -0
  44. data/lib/shoes/oval.rb +13 -8
  45. data/lib/shoes/packager.rb +7 -1
  46. data/lib/shoes/point.rb +26 -3
  47. data/lib/shoes/progress.rb +6 -8
  48. data/lib/shoes/rect.rb +14 -10
  49. data/lib/shoes/shape.rb +28 -14
  50. data/lib/shoes/slot.rb +33 -24
  51. data/lib/shoes/slot_contents.rb +4 -4
  52. data/lib/shoes/star.rb +7 -16
  53. data/lib/shoes/text.rb +5 -3
  54. data/lib/shoes/text_block.rb +17 -16
  55. data/lib/shoes/text_block_dimensions.rb +1 -1
  56. data/lib/shoes/ui/cli.rb +12 -3
  57. data/lib/shoes/ui/picker.rb +64 -19
  58. data/lib/shoes/version.rb +1 -1
  59. data/shoes-core.gemspec +2 -2
  60. data/spec/shoes/animation_spec.rb +1 -1
  61. data/spec/shoes/app_spec.rb +4 -23
  62. data/spec/shoes/color_spec.rb +16 -1
  63. data/spec/shoes/common/style_normalizer_spec.rb +3 -3
  64. data/spec/shoes/common/style_spec.rb +42 -5
  65. data/spec/shoes/dimension_spec.rb +5 -7
  66. data/spec/shoes/dimensions_spec.rb +7 -7
  67. data/spec/shoes/download_spec.rb +49 -8
  68. data/spec/shoes/flow_spec.rb +1 -1
  69. data/spec/shoes/helpers/fake_element.rb +7 -0
  70. data/spec/shoes/helpers/sample17_helper.rb +3 -3
  71. data/spec/shoes/integration_spec.rb +1 -1
  72. data/spec/shoes/internal_app_spec.rb +8 -0
  73. data/spec/shoes/line_spec.rb +35 -3
  74. data/spec/shoes/link_spec.rb +24 -12
  75. data/spec/shoes/list_box_spec.rb +14 -2
  76. data/spec/shoes/point_spec.rb +28 -0
  77. data/spec/shoes/renamed_delegate_spec.rb +2 -2
  78. data/spec/shoes/shape_spec.rb +15 -2
  79. data/spec/shoes/shared_examples/changeable.rb +1 -1
  80. data/spec/shoes/shared_examples/common_methods.rb +1 -1
  81. data/spec/shoes/shared_examples/dsl/style.rb +1 -1
  82. data/spec/shoes/shared_examples/dsl/text_elements.rb +3 -3
  83. data/spec/shoes/shared_examples/dsl/video.rb +1 -1
  84. data/spec/shoes/shared_examples/dsl_app_context.rb +0 -1
  85. data/spec/shoes/shared_examples/parent.rb +1 -1
  86. data/spec/shoes/shared_examples/slot.rb +11 -5
  87. data/spec/shoes/shared_examples/state.rb +2 -2
  88. data/spec/shoes/shared_examples/style.rb +1 -1
  89. data/spec/shoes/spec_helper.rb +1 -1
  90. data/spec/shoes/text_block_spec.rb +20 -3
  91. data/spec/shoes/ui/picker_spec.rb +70 -0
  92. metadata +8 -2
@@ -15,10 +15,8 @@ describe Shoes::Download do
15
15
  let(:length) {download.length}
16
16
  let(:content_length) {download.content_length}
17
17
 
18
- let(:bound_block) { Proc.new {} }
19
-
20
18
  before do
21
- expect(app.current_slot).to receive(:create_bound_block).at_least(1) { |blk| blk ? bound_block : nil }
19
+ expect(app.current_slot).to receive(:create_bound_block).at_least(1) { |blk| blk ? blk : nil }
22
20
 
23
21
  stub_request(:get, name)
24
22
  .to_return(:status => response_status, :body => response_body, :headers => response_headers)
@@ -79,7 +77,7 @@ describe Shoes::Download do
79
77
  context 'with content length' do
80
78
  it 'calls the progress proc from start, download and finish' do
81
79
  expect(download.gui).to have_received(:eval_block).
82
- with(bound_block, download).
80
+ with(progress_proc, download).
83
81
  exactly(3).times
84
82
  end
85
83
  end
@@ -89,9 +87,13 @@ describe Shoes::Download do
89
87
 
90
88
  it 'does not call on progress, but called from content length and finish' do
91
89
  expect(download.gui).to have_received(:eval_block).
92
- with(bound_block, download).
90
+ with(progress_proc, download).
93
91
  twice
94
92
  end
93
+
94
+ it 'can call percent just fine thanks' do
95
+ expect(download.percent).to eq(0)
96
+ end
95
97
  end
96
98
  end
97
99
 
@@ -107,7 +109,7 @@ describe Shoes::Download do
107
109
 
108
110
  context 'with a block' do
109
111
  it 'calls the block with a result' do
110
- expect(download.gui).to have_received(:eval_block).with(bound_block, result)
112
+ expect(download.gui).to have_received(:eval_block).with(input_block, result)
111
113
  end
112
114
 
113
115
  describe 'response object' do
@@ -134,13 +136,52 @@ describe Shoes::Download do
134
136
  end
135
137
 
136
138
  context 'with a finish proc' do
137
- let(:opts) { {save: "nasa50th.gif", finish: input_block} }
139
+ let(:finish_proc) { Proc.new {} }
140
+ let(:opts) { {save: "nasa50th.gif", finish: finish_proc} }
138
141
  subject(:download) { Shoes::Download.new app, parent, name, opts }
139
142
 
140
143
  it 'calls the finish proc' do
141
- expect(download.gui).to have_received(:eval_block).with(bound_block, subject)
144
+ expect(download.gui).to have_received(:eval_block).with(finish_proc, subject)
142
145
  end
143
146
  end
144
147
 
145
148
  end
149
+
150
+ describe 'when things go wrong' do
151
+ it 'reports back to the parent thread' do
152
+ error = StandardError.new("Nope")
153
+
154
+ expect(download.gui).to receive(:eval_block).with(anything, error)
155
+ allow(download).to receive(:open).and_raise(error)
156
+
157
+ download.start
158
+ download.join_thread
159
+ end
160
+
161
+ it 'does not die on socket errors, but logs them' do
162
+ error = SocketError.new('Badumz')
163
+
164
+ expect(download.gui).not_to receive(:eval_block)
165
+ expect(Shoes.logger).to receive(:error).with error
166
+ allow(download).to receive(:open).and_raise(error)
167
+
168
+ download.start
169
+ download.join_thread
170
+ end
171
+
172
+ describe 'with custom error blocks' do
173
+ let(:error_proc) { Proc.new { } }
174
+ let(:opts) { {save: "nasa50th.gif", error: error_proc} }
175
+
176
+ it 'gets called' do
177
+ error = StandardError.new("Nope")
178
+
179
+ expect(download.gui).to receive(:eval_block).with(error_proc, error)
180
+ allow(download).to receive(:open).and_raise(error)
181
+
182
+ download.start
183
+ download.join_thread
184
+ end
185
+ end
186
+ end
146
187
  end
@@ -37,7 +37,7 @@ describe Shoes::Flow do
37
37
  expect(flow).to receive(:clear) do |&blk|
38
38
  expect(blk).to eq(input_block)
39
39
  end
40
- flow.clear &input_block
40
+ flow.clear(&input_block)
41
41
  end
42
42
 
43
43
  describe "positioning" do
@@ -12,6 +12,13 @@ class Shoes
12
12
  def adjust_current_position(*_)
13
13
  end
14
14
 
15
+ # Fake this out instead of using Common::Style to avoid things like touching
16
+ # app level styles, etc. that we don't need for testing purposes
17
+ def style
18
+ @style ||= {}
19
+ @style
20
+ end
21
+
15
22
  attr_accessor :parent, :gui
16
23
  end
17
24
  end
@@ -10,16 +10,16 @@
10
10
  # end
11
11
  #
12
12
  class Sample17Helper
13
-
13
+
14
14
  def initialize(app)
15
15
  # This gives us the Shoes::App
16
16
  @app = app.app
17
17
  end
18
-
18
+
19
19
  def create_para
20
20
  @app.para("Testing, test, test. ", strong_breadsticks, em, code, bg, sub)
21
21
  end
22
-
22
+
23
23
  def breadsticks
24
24
  "Breadsticks. "
25
25
  end
@@ -17,4 +17,4 @@ describe 'Integration specs' do
17
17
  end.not_to raise_error
18
18
  end
19
19
  end
20
- end
20
+ end
@@ -65,6 +65,14 @@ describe Shoes::InternalApp do
65
65
  end
66
66
  end
67
67
 
68
+ describe '#inspect' do
69
+ let(:input_opts) {{title: 'Dupa'}}
70
+
71
+ it 'shows the title in inspect' do
72
+ expect(subject.inspect).to include 'Dupa'
73
+ end
74
+ end
75
+
68
76
  describe '#clear' do
69
77
  context 'when called after the initial input block' do
70
78
  let(:input_block) {
@@ -19,7 +19,7 @@ describe Shoes::Line do
19
19
  it_behaves_like 'object with parent'
20
20
  end
21
21
 
22
- context "line with point a at leftmost, topmost" do
22
+ describe "line with point a at leftmost, topmost" do
23
23
  subject { Shoes::Line.new(app, app, Shoes::Point.new(10, 15), Shoes::Point.new(100, 60), input_opts) }
24
24
  its(:left) { should eq(10) }
25
25
  its(:top) { should eq(15) }
@@ -29,7 +29,7 @@ describe Shoes::Line do
29
29
  its(:height) { should eq(45) }
30
30
  end
31
31
 
32
- context "specified right-to-left, top-to-bottom" do
32
+ describe "specified right-to-left, top-to-bottom" do
33
33
  subject { Shoes::Line.new(app, app, Shoes::Point.new(100, 60), Shoes::Point.new(10, 15), input_opts) }
34
34
  its(:left) { should eq(100) }
35
35
  its(:top) { should eq(60) }
@@ -39,7 +39,7 @@ describe Shoes::Line do
39
39
  its(:height) { should eq(-45) }
40
40
  end
41
41
 
42
- context "setting dimensions" do
42
+ describe "setting dimensions" do
43
43
  subject { Shoes::Line.new(app, app, Shoes::Point.new(100, 100), Shoes::Point.new(200, 200), input_opts) }
44
44
 
45
45
  it "moves point a with left and top" do
@@ -84,4 +84,36 @@ describe Shoes::Line do
84
84
  expect(subject.point_b).to eq(Shoes::Point.new(20, 20))
85
85
  end
86
86
  end
87
+
88
+ describe "#in_bounds?" do
89
+ subject(:line) { Shoes::Line.new(app, app, Shoes::Point.new(100, 100), Shoes::Point.new(50, 50), input_opts) }
90
+
91
+ it "returns true if a point is in the end of the line" do
92
+ expect(subject.in_bounds?(100, 100)).to be true
93
+ end
94
+
95
+ it "returns true if a point is in the end of the line" do
96
+ expect(subject.in_bounds?(50, 50)).to be true
97
+ end
98
+
99
+ it "returns true if a point is in the middle of the line" do
100
+ expect(subject.in_bounds?(75, 75)).to be true
101
+ end
102
+
103
+ it "returns false if a point is not in the line" do
104
+ expect(subject.in_bounds?(201, 200)).to be false
105
+ end
106
+
107
+ it "takes into account :strokewidth style" do
108
+ line = Shoes::Line.new(app, app, Shoes::Point.new(50, 50), Shoes::Point.new(70, 50), input_opts)
109
+ line.style(strokewidth: 20)
110
+ expect(line.in_bounds?(50, 52)).to be true
111
+ expect(line.in_bounds?(50, 48)).to be true
112
+ expect(line.in_bounds?(50, 60)).to be true
113
+ expect(line.in_bounds?(50, 40)).to be true
114
+ expect(line.in_bounds?(49, 50)).to be false
115
+ expect(line.in_bounds?(50, 61)).to be false
116
+ expect(line.in_bounds?(70, 50)).to be true
117
+ end
118
+ end
87
119
  end
@@ -2,11 +2,11 @@ require 'shoes/spec_helper'
2
2
 
3
3
  describe Shoes::Link do
4
4
  let(:gui) { double("gui").as_null_object }
5
- let(:app) { double("app", gui: gui, style: {}, element_styles: {}) }
5
+ let(:app) { double("app", gui: gui, style: {}, element_styles: {}, warn: true) }
6
6
  let(:internal_app) { double("internal app", app: app, gui: gui, style: {}, element_styles: {}) }
7
7
  let(:texts) { ["text", "goes", "first"] }
8
8
 
9
- subject { Shoes::Link.new(app, texts, {color: :blue}) }
9
+ subject { Shoes::Link.new(app, texts, color: :blue) }
10
10
 
11
11
  context "initialize" do
12
12
  it "should set up text" do
@@ -88,23 +88,35 @@ describe Shoes::Link do
88
88
  describe 'visibility' do
89
89
  let(:text_block) {double 'text block', visible?: true, hidden?: false}
90
90
 
91
- before :each do
92
- subject.text_block = text_block
93
- end
91
+ describe 'with a containing text block' do
92
+ before :each do
93
+ subject.text_block = text_block
94
+ end
95
+
96
+ it 'forwards #visible? calls' do
97
+ subject.visible?
98
+ expect(text_block).to have_received :visible?
99
+ end
94
100
 
95
- it 'forwards visible? calls' do
96
- subject.visible?
97
- expect(text_block).to have_received :visible?
101
+ it 'forwards #hidden? calls' do
102
+ subject.hidden?
103
+ expect(text_block).to have_received :hidden?
104
+ end
98
105
  end
99
106
 
100
- it 'forwards hidden? calls' do
101
- subject.hidden?
102
- expect(text_block).to have_received :hidden?
107
+ describe 'without a containing text block' do
108
+ it 'does not crash on #visibie?' do
109
+ expect {subject.visible?}.not_to raise_error
110
+ end
111
+
112
+ it 'does not crash on #hidden?' do
113
+ expect {subject.hidden?}.not_to raise_error
114
+ end
103
115
  end
104
116
  end
105
117
 
106
118
  # #979
107
- describe 'parent' do
119
+ describe 'containing text block' do
108
120
  let(:text_block) {double 'text block'}
109
121
 
110
122
  before :each do
@@ -41,6 +41,18 @@ describe Shoes::ListBox do
41
41
  expect(list_box.items).to eq(["Pie", "Apple", "Pig"])
42
42
  end
43
43
 
44
+ describe 'Updating gui' do
45
+ it "updates the gui when array methods like size are called" do
46
+ expect(list_box.gui).to receive(:update_items)
47
+ list_box.items.size
48
+ end
49
+
50
+ it "updates the gui when self-modifying array methods like map! are called" do
51
+ expect(list_box.gui).to receive(:update_items)
52
+ list_box.items.map!{"replaced!"}
53
+ end
54
+ end
55
+
44
56
  describe 'Choosing' do
45
57
  it "allows us to choose an option" do
46
58
  expect(list_box).to respond_to(:choose)
@@ -56,8 +68,8 @@ describe Shoes::ListBox do
56
68
  list_box.choose "Wine"
57
69
  end
58
70
 
59
- it 'should call @gui.choose when the choose option is passed' do
60
- expect_gui_choose_with 'Wine'
71
+ it 'should not call @gui.choose when the choose option is passed' do
72
+ expect_any_instance_of(Shoes.configuration.backend::ListBox).to_not receive(:choose)
61
73
  Shoes::ListBox.new app, parent, input_opts.merge(choose: 'Wine')
62
74
  end
63
75
  end
@@ -29,6 +29,34 @@ describe Shoes::Point do
29
29
  end
30
30
  end
31
31
 
32
+ describe "#+" do
33
+ it "performs element-wise addition with other point" do
34
+ expect(subject + Shoes::Point.new(40, 50)).to eq(Shoes::Point.new(80, 100))
35
+ end
36
+
37
+ it "performs element-wise addition with an array" do
38
+ expect(subject + [40, 50]).to eq(Shoes::Point.new(80, 100))
39
+ end
40
+
41
+ it "doesn't perform addition when dimensions don't match" do
42
+ expect { subject + [40, 50, 60] }.to raise_error(ArgumentError)
43
+ end
44
+ end
45
+
46
+ describe "#-" do
47
+ it "performs element-wise subtraction with other point" do
48
+ expect(subject - Shoes::Point.new(40, 50)).to eq(Shoes::Point.new(0, 0))
49
+ end
50
+
51
+ it "performs element-wise subtraction with an array" do
52
+ expect(subject - [40, 50]).to eq(Shoes::Point.new(0, 0))
53
+ end
54
+
55
+ it "doesn't perform subtraction when dimensions don't match" do
56
+ expect { subject - [40, 50, 60] }.to raise_error(ArgumentError)
57
+ end
58
+ end
59
+
32
60
  describe "#to" do
33
61
  it "positive" do
34
62
  expect(subject.to(24, 166)).to eq(Shoes::Point.new(64, 216))
@@ -34,7 +34,7 @@ describe RenamedDelegate do
34
34
 
35
35
  TestClass.renamed_delegate_to :delegate,
36
36
  ToDelegate.public_instance_methods(false),
37
- {'key' => 'shoes', 'something' => 'awesome'}
37
+ 'key' => 'shoes', 'something' => 'awesome'
38
38
 
39
39
  let(:delegate) {double('delegate').as_null_object}
40
40
  subject {TestClass.new delegate}
@@ -67,4 +67,4 @@ describe RenamedDelegate do
67
67
  it 'does not define a method for methods without renamings' do
68
68
  expect(subject).not_to respond_to :abcd
69
69
  end
70
- end
70
+ end
@@ -16,6 +16,7 @@ describe Shoes::Shape do
16
16
  end
17
17
 
18
18
  it_behaves_like "movable object"
19
+ it_behaves_like "clickable object"
19
20
 
20
21
  describe "octagon" do
21
22
  let(:draw) {
@@ -44,7 +45,7 @@ describe Shoes::Shape do
44
45
  describe "when created without left and top values" do
45
46
  let(:left) { nil }
46
47
  let(:top) { nil }
47
-
48
+
48
49
  its(:left) { should eq(nil) }
49
50
  its(:top) { should eq(nil) }
50
51
  end
@@ -85,13 +86,25 @@ describe Shoes::Shape do
85
86
  describe "arc" do
86
87
  let(:draw) {
87
88
  Proc.new {
88
- arc 10, 10, 100, 100, Shoes::PI, Shoes::TWO_PI
89
+ arc_to 10, 10, 100, 100, Shoes::PI, Shoes::TWO_PI
89
90
  }
90
91
  }
91
92
 
92
93
  it_behaves_like "movable object"
93
94
  end
94
95
 
96
+ describe "in_bounds?" do
97
+ let(:draw) { Proc.new { line_to 100, 100 } }
98
+
99
+ it "is in bounds" do
100
+ expect(subject.in_bounds?(10, 10)).to be true
101
+ end
102
+
103
+ it "is out of bounds" do
104
+ expect(subject.in_bounds?(101, 101)).to be false
105
+ end
106
+ end
107
+
95
108
  describe "accesses app" do
96
109
  let(:draw) {
97
110
  Proc.new {
@@ -9,7 +9,7 @@ shared_examples "an element that can respond to change" do
9
9
  describe "when setting up a callback with #change" do
10
10
  it "should notify the callback of change events" do
11
11
  called = false
12
- subject.change do |element|
12
+ subject.change do
13
13
  called = true
14
14
  end
15
15
  subject.call_change_listeners
@@ -24,7 +24,7 @@ shared_examples_for "movable object" do
24
24
  end
25
25
  end
26
26
 
27
- shared_examples_for "left, top as center" do | *params |
27
+ shared_examples_for "left, top as center" do |*params|
28
28
  let(:centered_object) { described_class.new(app, parent, left, top, width, height, *params, :center => true) }
29
29
  it "should now be located somewhere" do
30
30
  expect(centered_object.left).to eq(left-(width/2))
@@ -3,7 +3,7 @@ shared_examples_for "style DSL method" do
3
3
  let(:stroke) { Shoes::COLORS[:chartreuse] }
4
4
  let(:size) { 42 }
5
5
  let(:fill) { Shoes::COLORS[:peru] }
6
- let(:font ) { "SOME FONT" }
6
+ let(:font) { "SOME FONT" }
7
7
  let(:style) { {:stroke => stroke, :size => size, :fill => fill, :font => font} }
8
8
 
9
9
  %w(Banner Title Subtitle Tagline Caption Para Inscription).each do |text_block|
@@ -41,17 +41,17 @@ shared_examples_for "text element DSL methods" do
41
41
  end
42
42
 
43
43
  it 'should handle a splatted array of links' do
44
- expect{dsl.span *[dsl.link('foo'), dsl.link('foo')]}.not_to raise_error
44
+ expect{dsl.span(*[dsl.link('foo'), dsl.link('foo')])}.not_to raise_error
45
45
  end
46
46
 
47
47
  it 'should handle a splatted array of links and parse the color' do
48
- span = dsl.span *[dsl.link('foo'), dsl.link('foo')], stroke: '#ccc'
48
+ span = dsl.span(*[dsl.link('foo'), dsl.link('foo')], stroke: '#ccc')
49
49
  expect(span.style[:stroke]).to eq Shoes::Color.new 204, 204, 204
50
50
  end
51
51
 
52
52
  it 'should handle a splatted array of links with a block' do
53
53
  link = dsl.link('foo') { "Bar" }
54
- expect{dsl.span *[link, link]}.not_to raise_error
54
+ expect{dsl.span(*[link, link])}.not_to raise_error
55
55
  end
56
56
  end
57
57
 
@@ -2,4 +2,4 @@ shared_examples_for 'video DSL method' do
2
2
  it 'throws a Shoes::NotImplementedError' do
3
3
  expect{dsl.video}.to raise_error Shoes::NotImplementedError
4
4
  end
5
- end
5
+ end
@@ -5,4 +5,3 @@ shared_context "dsl app" do
5
5
  let(:app) { user_facing_app.instance_variable_get(:@__app__) }
6
6
  let(:parent) { Shoes::Flow.new app, app }
7
7
  end
8
-
@@ -3,4 +3,4 @@ shared_examples_for 'object with parent' do
3
3
  it 'has a getter for the parent' do
4
4
  expect(subject.parent).to eq parent
5
5
  end
6
- end
6
+ end
@@ -108,6 +108,12 @@ shared_examples_for 'positioning through :_position' do
108
108
  expect(element).not_to receive(:_position)
109
109
  subject.contents_alignment
110
110
  end
111
+
112
+ it 'is resilient to exceptions during positioning' do
113
+ allow(element).to receive(:contents_alignment).and_raise("O_o")
114
+ allow(subject).to receive(:puts) # Quiet, you
115
+ add_child_and_align
116
+ end
111
117
  end
112
118
 
113
119
  shared_examples_for 'element one positioned with top and left' do
@@ -127,11 +133,11 @@ shared_examples_for 'element one positioned with bottom and right' do
127
133
  include_context 'slot with set height and width'
128
134
 
129
135
  it 'positions the element from its right' do
130
- expect(element.absolute_right).to eq (subject.absolute_right - ele_right - 1)
136
+ expect(element.absolute_right).to eq(subject.absolute_right - ele_right - 1)
131
137
  end
132
138
 
133
139
  it 'positions the element from its bottom' do
134
- expect(element.absolute_bottom).to eq (subject.absolute_bottom - ele_bottom - 1)
140
+ expect(element.absolute_bottom).to eq(subject.absolute_bottom - ele_bottom - 1)
135
141
  end
136
142
  end
137
143
 
@@ -169,11 +175,11 @@ shared_examples_for 'arranges elements underneath each other' do
169
175
  end
170
176
 
171
177
  it 'has a stack height according to its contents' do
172
- expect(subject.height).to eq (element.height + element2.height)
178
+ expect(subject.height).to eq(element.height + element2.height)
173
179
  end
174
180
 
175
181
  it 'has an absolute_bottom of top + height' do
176
- expect(subject.absolute_bottom).to eq (subject.absolute_top + subject.height - 1)
182
+ expect(subject.absolute_bottom).to eq(subject.absolute_top + subject.height - 1)
177
183
  end
178
184
 
179
185
  describe 'element one with top and left' do
@@ -196,7 +202,7 @@ shared_examples_for 'set height and contents alignment' do
196
202
  include_context 'two slot children'
197
203
 
198
204
  it 'contents_alignment returns the height of the content' do
199
- expect(subject.contents_alignment).to eq (element.height + element2.height)
205
+ expect(subject.contents_alignment).to eq(element.height + element2.height)
200
206
  end
201
207
 
202
208
  it 'still has the same height though' do
@@ -8,7 +8,7 @@ shared_examples_for "object with state" do
8
8
  it "should enable" do
9
9
  expect(subject.gui).to receive(:enabled).with(true)
10
10
  subject.state = nil
11
- expect(subject.state).to eq(nil)
11
+ expect(subject.state).to eq(nil)
12
12
  end
13
13
 
14
14
  it "should disable" do
@@ -16,4 +16,4 @@ shared_examples_for "object with state" do
16
16
  subject.state = "disabled"
17
17
  expect(subject.state).to eq("disabled")
18
18
  end
19
- end
19
+ end
@@ -9,7 +9,7 @@ shared_examples_for "object with style" do
9
9
  end
10
10
 
11
11
  describe 'using app-level styles' do
12
-
12
+
13
13
  it 'initially uses app defaults' do
14
14
  app.style.each do |key, value|
15
15
  expect(subject.style[key]).to eq(value) if uses_app_default? key
@@ -9,7 +9,7 @@ def unpack_styles(styles)
9
9
  supported_styles = []
10
10
  styles.each do |style|
11
11
  if Shoes::Common::Style::STYLE_GROUPS[style]
12
- Shoes::Common::Style::STYLE_GROUPS[style].each{|style| supported_styles << style}
12
+ Shoes::Common::Style::STYLE_GROUPS[style].each{|s| supported_styles << s}
13
13
  else
14
14
  supported_styles << style
15
15
  end
@@ -6,7 +6,7 @@ describe Shoes::TextBlock do
6
6
 
7
7
  let(:text_link) { Shoes::Link.new(app, ['Hello']) }
8
8
  let(:text) { [text_link, ", world!"] }
9
- subject(:text_block) { Shoes::TextBlock.new(app, parent, text, {app: app}) }
9
+ subject(:text_block) { Shoes::TextBlock.new(app, parent, text, app: app) }
10
10
 
11
11
  it_behaves_like "object with style" do
12
12
  let(:subject_without_style) { Shoes::TextBlock.new(app, parent, text) }
@@ -72,6 +72,17 @@ describe Shoes::TextBlock do
72
72
  text_block.replace "Later Gator"
73
73
  expect(text_block.text_styles).to be_empty
74
74
  end
75
+
76
+ it "updates styles from options hash" do
77
+ text_block.replace "Later Gator", stroke: Shoes::COLORS[:aquamarine]
78
+ expect(text_block.stroke).to eq(Shoes::COLORS[:aquamarine])
79
+ end
80
+
81
+ it "updates font from options hash" do
82
+ text_block.replace "Later Gator", font: 'Monospace 18px'
83
+ expect(text_block.font).to eq('Monospace')
84
+ expect(text_block.size).to eq(18)
85
+ end
75
86
  end
76
87
 
77
88
  describe "#contents" do
@@ -138,7 +149,7 @@ describe Shoes::TextBlock do
138
149
 
139
150
  describe "stroke" do
140
151
  it "should accept a hex code" do
141
- s = Shoes::TextBlock.new(app, parent, ["Hello, world!"], { stroke: "#fda", app: app })
152
+ s = Shoes::TextBlock.new(app, parent, ["Hello, world!"], stroke: "#fda", app: app)
142
153
  color = s.style[:stroke]
143
154
  expect(color.red).to eql 255
144
155
  expect(color.green).to eql 221
@@ -174,10 +185,16 @@ describe Shoes::TextBlock do
174
185
  subject.absolute_left = 20
175
186
  expect(subject.desired_width(1000)).to eql(980)
176
187
  end
188
+
189
+ it "factors margins into desired width" do
190
+ subject.absolute_left = 0
191
+ subject.margin = 10
192
+ expect(subject.desired_width(1000)).to eql(980)
193
+ end
177
194
  end
178
195
 
179
196
  context "when explicitly set" do
180
- subject(:text_block) { Shoes::TextBlock.new(app, parent, ["text"], { width: 120 }) }
197
+ subject(:text_block) { Shoes::TextBlock.new(app, parent, ["text"], width: 120) }
181
198
 
182
199
  it "gets returned" do
183
200
  expect(subject.width).to eql 120