shoes-core 4.0.0.pre3 → 4.0.0.pre4

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