vedeu 0.0.31 → 0.0.32

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -4
  3. data/lib/vedeu.rb +1 -0
  4. data/lib/vedeu/models/collection.rb +17 -0
  5. data/lib/vedeu/models/colour.rb +27 -5
  6. data/lib/vedeu/models/line_collection.rb +4 -9
  7. data/lib/vedeu/models/stream.rb +1 -1
  8. data/lib/vedeu/models/stream_collection.rb +4 -9
  9. data/lib/vedeu/support/coordinate.rb +149 -0
  10. data/lib/vedeu/support/esc.rb +4 -0
  11. data/lib/vedeu/support/menu.rb +103 -0
  12. data/lib/vedeu/support/terminal.rb +4 -0
  13. data/test/example_app/lib/app.rb +25 -6
  14. data/test/lib/vedeu/models/collection_test.rb +50 -0
  15. data/test/lib/vedeu/models/colour_test.rb +58 -1
  16. data/test/lib/vedeu/models/command_test.rb +2 -1
  17. data/test/lib/vedeu/models/interface_collection_test.rb +4 -3
  18. data/test/lib/vedeu/models/line_test.rb +3 -1
  19. data/test/lib/vedeu/models/stream_test.rb +6 -3
  20. data/test/lib/vedeu/output/text_adaptor_test.rb +1 -1
  21. data/test/lib/vedeu/repository/command_repository_test.rb +2 -1
  22. data/test/lib/vedeu/repository/interface_repository_test.rb +2 -1
  23. data/test/lib/vedeu/repository/repository_test.rb +2 -1
  24. data/test/lib/vedeu/repository/storage_test.rb +6 -3
  25. data/test/lib/vedeu/support/coordinate_test.rb +363 -0
  26. data/test/lib/vedeu/support/esc_test.rb +8 -0
  27. data/test/lib/vedeu/support/menu_test.rb +202 -0
  28. data/test/lib/vedeu/support/parser_test.rb +2 -1
  29. data/test/lib/vedeu/support/parsing/hash_parser_test.rb +6 -3
  30. data/test/lib/vedeu/support/parsing/json_parser_test.rb +2 -1
  31. data/test/lib/vedeu/support/terminal_test.rb +9 -0
  32. data/test/lib/vedeu/support/translator_test.rb +2 -1
  33. data/test/test_helper.rb +12 -0
  34. data/vedeu.gemspec +1 -1
  35. metadata +11 -8
  36. data/lib/vedeu/models/background.rb +0 -13
  37. data/lib/vedeu/models/foreground.rb +0 -13
  38. data/test/lib/vedeu/models/background_test.rb +0 -19
  39. data/test/lib/vedeu/models/foreground_test.rb +0 -18
@@ -31,6 +31,10 @@ module Vedeu
31
31
  stream
32
32
  end
33
33
 
34
+ def centre
35
+ [(height / 2), (width / 2)]
36
+ end
37
+
34
38
  def width
35
39
  size.last
36
40
  end
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
+ require 'pry'
3
4
  require 'vedeu'
4
5
 
5
6
  module Example
@@ -35,16 +36,34 @@ module Example
35
36
  class App
36
37
  include Vedeu
37
38
 
39
+ def self.example_position
40
+ @_position = Vedeu::Coordinate.new({ width: 40, height: 5, centered: true }).position
41
+ end
42
+
43
+ def self.command_position
44
+ {
45
+ y: example_position[:bottom],
46
+ x: example_position[:x],
47
+ height: 1,
48
+ width: 40,
49
+ centered: true
50
+ }
51
+ end
52
+
38
53
  interface 'example', {
39
- y: 1, x: 1, width: 80, height: 5,
40
- colour: { background: '#ff0000', foreground: '#000000' },
54
+ colour: {
55
+ background: '#ff0000',
56
+ foreground: '#000000'
57
+ },
41
58
  cursor: false
42
- }
59
+ }.merge(example_position)
43
60
  interface 'command', {
44
- y: 6, x: 1, width: 80, height: 1,
45
- colour: { background: '#4040cc', foreground: '#aadd00' },
61
+ colour: {
62
+ background: '#4040cc',
63
+ foreground: '#aadd00'
64
+ },
46
65
  cursor: true
47
- }
66
+ }.merge(command_position)
48
67
  command 'time', {
49
68
  entity: ExampleCommand,
50
69
  keyword: 'time',
@@ -0,0 +1,50 @@
1
+ require_relative '../../../test_helper'
2
+ require_relative '../../../../lib/vedeu/models/collection'
3
+
4
+ module Vedeu
5
+ class TestClass
6
+ include Collection
7
+
8
+ def initialize(*args); end
9
+ end
10
+
11
+ describe Collection do
12
+ describe '#coercer' do
13
+ it 'returns an empty collection when nil or empty' do
14
+ Collection.coercer(nil, TestClass, :key).must_equal([])
15
+ end
16
+
17
+ it 'returns an empty collection when nil or empty' do
18
+ Collection.coercer('', TestClass, :key).must_equal([])
19
+ end
20
+
21
+ it 'returns an empty collection when nil or empty' do
22
+ Collection.coercer([], TestClass, :key).must_equal([])
23
+ end
24
+
25
+ it 'returns an empty collection when nil or empty' do
26
+ Collection.coercer({}, TestClass, :key).must_equal([])
27
+ end
28
+
29
+ it 'returns a single model in a collection when a String' do
30
+ Collection.coercer('test', TestClass, :key).size.must_equal(1)
31
+ end
32
+
33
+ it 'returns a collection of models when a single hash' do
34
+ Collection.coercer({ :test1 => 'test1' }, TestClass, :key)
35
+ .size.must_equal(1)
36
+ end
37
+
38
+ it 'returns a collection of models when multiple hashes' do
39
+ Collection.coercer([
40
+ { :test1 => 'test1' }, { :test2 => 'test2' }
41
+ ], TestClass, :key).size.must_equal(2)
42
+ end
43
+
44
+ it 'returns a collection of models when a single array' do
45
+ Collection.coercer([{ :test3 => 'test3' }], TestClass, :key)
46
+ .size.must_equal(1)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -3,12 +3,60 @@ require_relative '../../../../lib/vedeu/models/colour'
3
3
 
4
4
  module Vedeu
5
5
  describe Colour do
6
+ describe '#background' do
7
+ it 'returns an escape sequence' do
8
+ Colour.new({
9
+ background: '#000000'
10
+ }).background.must_equal("\e[48;5;16m")
11
+ end
12
+
13
+ it 'returns an empty string if the value is empty' do
14
+ Colour.new.background.must_equal('')
15
+ end
16
+ end
17
+
18
+ describe '#foreground' do
19
+ it 'returns an escape sequence' do
20
+ Colour.new({
21
+ foreground: '#ff0000'
22
+ }).foreground.must_equal("\e[38;5;196m")
23
+ end
24
+
25
+ it 'returns an empty string if the value is empty' do
26
+ Colour.new.foreground.must_equal('')
27
+ end
28
+ end
29
+
30
+ describe '#css_background' do
31
+ it 'returns an escape sequence' do
32
+ Colour.new({
33
+ background: '#000000'
34
+ }).css_background.must_equal('#000000')
35
+ end
36
+
37
+ it 'returns an empty string if the value is nil' do
38
+ Colour.new.css_background.must_equal('')
39
+ end
40
+ end
41
+
42
+ describe '#css_foreground' do
43
+ it 'returns an escape sequence' do
44
+ Colour.new({
45
+ foreground: '#ff0000'
46
+ }).css_foreground.must_equal('#ff0000')
47
+ end
48
+
49
+ it 'returns an empty string if the value is nil' do
50
+ Colour.new.css_foreground.must_equal('')
51
+ end
52
+ end
53
+
6
54
  describe '#to_json' do
7
55
  it 'returns the model as JSON' do
8
56
  Colour.new({
9
57
  foreground: '#ff0000',
10
58
  background: '#000000'
11
- }).to_json.must_equal("{\"foreground\":\"\\u001b[38;5;196m\",\"background\":\"\\u001b[48;5;16m\"}")
59
+ }).to_json.must_equal("{\"foreground\":\"#ff0000\",\"background\":\"#000000\"}")
12
60
  end
13
61
  end
14
62
 
@@ -36,5 +84,14 @@ module Vedeu
36
84
  Colour.new.to_s.must_equal('')
37
85
  end
38
86
  end
87
+
88
+ describe '#as_hash' do
89
+ it 'returns the model as a Hash' do
90
+ Colour.new({
91
+ foreground: '#ff0000',
92
+ background: '#000000'
93
+ }).as_hash.must_equal({ foreground: '#ff0000', background: '#000000' })
94
+ end
95
+ end
39
96
  end
40
97
  end
@@ -9,7 +9,8 @@ module Vedeu
9
9
  end
10
10
 
11
11
  it 'has an entity attribute' do
12
- Command.new({ entity: DummyCommand }).entity.must_equal(DummyCommand)
12
+ Command.new({ entity: DummyCommand }).entity
13
+ .must_equal(DummyCommand)
13
14
  end
14
15
 
15
16
  it 'has a keypress attribute' do
@@ -13,12 +13,13 @@ module Vedeu
13
13
  Composition.new.interfaces.must_equal([])
14
14
  end
15
15
 
16
- it 'returns a collection of Interface objects when there is a single interface' do
16
+ it 'returns a collection when there is a single interface' do
17
17
  skip
18
- Composition.new({ name: 'dummy' }).interfaces.first.must_be_instance_of(Interface)
18
+ Composition.new({ name: 'dummy' }).interfaces.first
19
+ .must_be_instance_of(Interface)
19
20
  end
20
21
 
21
- it 'returns a collection of Interface objects when there are multiple interfaces' do
22
+ it 'returns a collection when there are multiple interfaces' do
22
23
  Composition.new({ interfaces: [
23
24
  { name: 'dumb' },
24
25
  { name: 'dumber' }
@@ -8,7 +8,9 @@ module Vedeu
8
8
  end
9
9
 
10
10
  it 'has a colour attribute' do
11
- Line.new(colour: { foreground: '#ff0000', background: '#000000' }).colour.must_be_instance_of(Colour)
11
+ Line.new({
12
+ colour: { foreground: '#ff0000', background: '#000000' }
13
+ }).colour.must_be_instance_of(Colour)
12
14
  end
13
15
 
14
16
  it 'has a model attribute' do
@@ -4,7 +4,9 @@ require_relative '../../../../lib/vedeu/models/stream'
4
4
  module Vedeu
5
5
  describe Stream do
6
6
  it 'has a colour attribute' do
7
- Stream.new({ colour: { foreground: '#ff0000', background: '#000000' } }).colour.must_be_instance_of(Colour)
7
+ Stream.new({
8
+ colour: { foreground: '#ff0000', background: '#000000' }
9
+ }).colour.must_be_instance_of(Colour)
8
10
  end
9
11
 
10
12
  it 'has a text attribute' do
@@ -12,7 +14,8 @@ module Vedeu
12
14
  end
13
15
 
14
16
  it 'has a style attribute' do
15
- Stream.new({ style: 'normal' }).style.must_equal("\e[24m\e[21m\e[27m")
17
+ Stream.new({ style: 'normal' }).style
18
+ .must_equal("\e[24m\e[21m\e[27m")
16
19
  end
17
20
 
18
21
  describe '#to_s' do
@@ -31,7 +34,7 @@ module Vedeu
31
34
  style: 'normal',
32
35
  colour: { foreground: '#ff0000', background: '#000000' },
33
36
  text: 'Some text'
34
- }).to_json.must_equal("{\"colour\":{\"foreground\":\"\\u001b[38;5;196m\",\"background\":\"\\u001b[48;5;16m\"},\"style\":\"\\u001b[24m\\u001b[21m\\u001b[27m\",\"text\":\"Some text\"}")
37
+ }).to_json.must_equal("{\"colour\":{\"foreground\":\"#ff0000\",\"background\":\"#000000\"},\"style\":\"\\u001b[24m\\u001b[21m\\u001b[27m\",\"text\":\"Some text\"}")
35
38
  end
36
39
  end
37
40
  end
@@ -4,7 +4,7 @@ require_relative '../../../../lib/vedeu/output/text_adaptor'
4
4
  module Vedeu
5
5
  describe TextAdaptor do
6
6
  describe '.adapt' do
7
- it 'returns an empty collection when processing an empty string' do
7
+ it 'returns an empty collection for an empty string' do
8
8
  TextAdaptor.adapt('').must_be_empty
9
9
  end
10
10
 
@@ -34,7 +34,8 @@ module Vedeu
34
34
  end
35
35
 
36
36
  it 'returns FalseClass when no command was found' do
37
- CommandRepository.by_input('not_found').must_be_instance_of(FalseClass)
37
+ CommandRepository.by_input('not_found')
38
+ .must_be_instance_of(FalseClass)
38
39
  end
39
40
 
40
41
  it 'returns FalseClass when there is no input' do
@@ -20,7 +20,8 @@ module Vedeu
20
20
  width: 15,
21
21
  height: 2
22
22
  })
23
- InterfaceRepository.find('dummy').must_be_instance_of(Interface)
23
+ InterfaceRepository.find('dummy')
24
+ .must_be_instance_of(Interface)
24
25
  end
25
26
 
26
27
  it 'raises an exception when the interface does not exist' do
@@ -39,7 +39,8 @@ module Vedeu
39
39
  describe '#query' do
40
40
  it 'returns a Dummy' do
41
41
  dummy = DummyRepository.create(Dummy.new)
42
- DummyRepository.query(Dummy, :name, 'dummy').must_be_instance_of(Dummy)
42
+ DummyRepository.query(Dummy, :name, 'dummy')
43
+ .must_be_instance_of(Dummy)
43
44
  end
44
45
  end
45
46
 
@@ -6,13 +6,15 @@ module Vedeu
6
6
  describe Storage do
7
7
  describe '#create' do
8
8
  it 'returns the stored record' do
9
- Storage.new.create(DummyCommand.new).must_be_instance_of(DummyCommand)
9
+ Storage.new.create(DummyCommand.new)
10
+ .must_be_instance_of(DummyCommand)
10
11
  end
11
12
  end
12
13
 
13
14
  describe '#delete' do
14
15
  it 'returns a NilClass' do
15
- Storage.new.delete(DummyCommand.new).must_be_instance_of(NilClass)
16
+ Storage.new.delete(DummyCommand.new)
17
+ .must_be_instance_of(NilClass)
16
18
  end
17
19
  end
18
20
 
@@ -36,7 +38,8 @@ module Vedeu
36
38
 
37
39
  describe '#query' do
38
40
  it 'returns a FalseClass when the item cannot be found' do
39
- Storage.new.query(nil, nil, nil).must_be_instance_of(FalseClass)
41
+ Storage.new.query(nil, nil, nil)
42
+ .must_be_instance_of(FalseClass)
40
43
  end
41
44
  end
42
45
  end
@@ -0,0 +1,363 @@
1
+ require_relative '../../../test_helper'
2
+ require_relative '../../../../lib/vedeu/support/coordinate'
3
+
4
+ module Vedeu
5
+ describe Coordinate do
6
+ it 'raises an exception when the height attribute is not set' do
7
+ proc { Coordinate.new({ width: 18 }) }.must_raise(KeyError)
8
+ end
9
+
10
+ it 'raises an exception when the width attribute is not set' do
11
+ proc { Coordinate.new({ height: 6 }) }.must_raise(KeyError)
12
+ end
13
+
14
+ describe '#terminal_height' do
15
+ it 'raises an exception if the value is less than 1' do
16
+ coordinate = Coordinate.new({ height: 6, width: 18, terminal_height: -2 })
17
+ proc { coordinate.terminal_height }.must_raise(OutOfBoundsError)
18
+ end
19
+
20
+ it 'raises an exception if the value is greater than the terminal height' do
21
+ console = IO.console
22
+ console.stub :winsize, [25, 80] do
23
+ coordinate = Coordinate.new({ height: 6, width: 18, terminal_height: 30 })
24
+ proc { coordinate.terminal_height }.must_raise(OutOfBoundsError)
25
+ end
26
+ end
27
+
28
+ it 'returns the value of terminal_height' do
29
+ console = IO.console
30
+ console.stub :winsize, [25, 80] do
31
+ Coordinate.new({ height: 6, width: 18, terminal_height: 20 })
32
+ .terminal_height.must_equal(20)
33
+ end
34
+ end
35
+
36
+ it 'returns the default height if not set' do
37
+ console = IO.console
38
+ console.stub :winsize, [25, 80] do
39
+ Coordinate.new({ height: 6, width: 18 })
40
+ .instance_variable_get('@terminal_height').must_equal(25)
41
+ end
42
+ end
43
+ end
44
+
45
+ describe '#height' do
46
+ it 'raises an exception if the value is less than 1' do
47
+ coordinate = Coordinate.new({ height: -6, width: 18 })
48
+ proc { coordinate.height }.must_raise(OutOfBoundsError)
49
+ end
50
+
51
+ it 'raises an exception if the value is greater than the terminal height' do
52
+ console = IO.console
53
+ console.stub :winsize, [25, 80] do
54
+ coordinate = Coordinate.new({ height: 30, width: 18 })
55
+ proc { coordinate.height }.must_raise(OutOfBoundsError)
56
+ end
57
+ end
58
+
59
+ it 'returns the value of height' do
60
+ Coordinate.new({ height: 6, width: 18 }).height.must_equal(6)
61
+ end
62
+ end
63
+
64
+ describe '#y' do
65
+ it 'raises an exception if the value is less than 1' do
66
+ coordinate = Coordinate.new({ height: 6, width: 18, y: -2 })
67
+ proc { coordinate.y }.must_raise(OutOfBoundsError)
68
+ end
69
+
70
+ it 'raises an exception if the value is greater than the terminal height' do
71
+ console = IO.console
72
+ console.stub :winsize, [25, 80] do
73
+ coordinate = Coordinate.new({ height: 6, width: 18, y: 30 })
74
+ proc { coordinate.y }.must_raise(OutOfBoundsError)
75
+ end
76
+ end
77
+
78
+ it 'returns the value of y' do
79
+ Coordinate.new({ height: 6, width: 18, y: 6 }).y.must_equal(6)
80
+ end
81
+
82
+ it 'returns 1 if not set' do
83
+ Coordinate.new({ height: 6, width: 18 }).y.must_equal(1)
84
+ end
85
+ end
86
+
87
+ describe '#terminal_width' do
88
+ it 'raises an exception if the value is less than 1' do
89
+ coordinate = Coordinate.new({ height: 6, width: 18, terminal_width: -2 })
90
+ proc { coordinate.terminal_width }.must_raise(OutOfBoundsError)
91
+ end
92
+
93
+ it 'raises an exception if the value is greater than the terminal width' do
94
+ console = IO.console
95
+ console.stub :winsize, [25, 80] do
96
+ coordinate = Coordinate.new({ height: 6, width: 18, terminal_width: 85 })
97
+ proc { coordinate.terminal_width }.must_raise(OutOfBoundsError)
98
+ end
99
+ end
100
+
101
+ it 'returns the value of terminal_width' do
102
+ console = IO.console
103
+ console.stub :winsize, [25, 80] do
104
+ Coordinate.new({ height: 6, width: 18, terminal_width: 40 })
105
+ .terminal_width.must_equal(40)
106
+ end
107
+ end
108
+
109
+ it 'returns the default width if not set' do
110
+ console = IO.console
111
+ console.stub :winsize, [25, 80] do
112
+ Coordinate.new({ height: 6, width: 18 })
113
+ .terminal_width.must_equal(80)
114
+ end
115
+ end
116
+ end
117
+
118
+ describe '#width' do
119
+ it 'raises an exception if the value is less than 1' do
120
+ coordinate = Coordinate.new({ height: 6, width: -18 })
121
+ proc { coordinate.width }.must_raise(OutOfBoundsError)
122
+ end
123
+
124
+ it 'raises an exception if the value is greater than the terminal width' do
125
+ console = IO.console
126
+ console.stub :winsize, [25, 80] do
127
+ coordinate = Coordinate.new({ height: 6, width: 85 })
128
+ proc { coordinate.width }.must_raise(OutOfBoundsError)
129
+ end
130
+ end
131
+
132
+ it 'returns the value of width' do
133
+ Coordinate.new({ height: 6, width: 18, x: 6 }).width
134
+ .must_equal(18)
135
+ end
136
+ end
137
+
138
+ describe '#x' do
139
+ it 'raises an exception if the value is less than 1' do
140
+ coordinate = Coordinate.new({ height: 6, width: 18, x: -2 })
141
+ proc { coordinate.x }.must_raise(OutOfBoundsError)
142
+ end
143
+
144
+ it 'raises an exception if the value is greater than the terminal width' do
145
+ console = IO.console
146
+ console.stub :winsize, [25, 80] do
147
+ coordinate = Coordinate.new({ height: 6, width: 18, x: 85 })
148
+ proc { coordinate.x }.must_raise(OutOfBoundsError)
149
+ end
150
+ end
151
+
152
+ it 'returns the value of x' do
153
+ Coordinate.new({ height: 6, width: 18, x: 6 }).x.must_equal(6)
154
+ end
155
+
156
+ it 'returns 1 if not set' do
157
+ Coordinate.new({ height: 6, width: 18 }).x.must_equal(1)
158
+ end
159
+ end
160
+
161
+ describe '#centered' do
162
+ it 'has a centred attribute' do
163
+ Coordinate.new({ height: 6, width: 18, centred: false })
164
+ .centred.must_equal(false)
165
+ end
166
+
167
+ it 'sets the centred attribute to true if not set' do
168
+ Coordinate.new({ height: 6, width: 18 })
169
+ .centred.must_equal(true)
170
+ end
171
+ end
172
+
173
+ describe '#centre' do
174
+ it 'returns a tuple containing the default centre coordinates' do
175
+ console = IO.console
176
+ console.stub :winsize, [25, 80] do
177
+ coordinate = Coordinate.new({ height: 6, width: 18 })
178
+ coordinate.centre.must_equal([12, 40])
179
+ end
180
+ end
181
+
182
+ it 'returns a tuple containing the centre coordinates' do
183
+ coordinate = Coordinate.new({ height: 6, width: 18, terminal_height: 12, terminal_width: 40 })
184
+ coordinate.centre.must_equal([6, 20])
185
+ end
186
+
187
+ it 'returns a tuple containing the centre coordinates when an' \
188
+ ' alternative terminal height is set' do
189
+ console = IO.console
190
+ console.stub :winsize, [25, 80] do
191
+ coordinate = Coordinate.new({ height: 6, width: 18, terminal_height: 12 })
192
+ coordinate.centre.must_equal([6, 40])
193
+ end
194
+ end
195
+
196
+ it 'returns a tuple containing the centre coordinates when an' \
197
+ ' alternative terminal width is set' do
198
+ console = IO.console
199
+ console.stub :winsize, [25, 80] do
200
+ coordinate = Coordinate.new({ height: 6, width: 18, terminal_width: 40 })
201
+ coordinate.centre.must_equal([12, 20])
202
+ end
203
+ end
204
+ end
205
+
206
+ describe '#top' do
207
+ it 'centred is true and terminal height is set' do
208
+ coordinate = Coordinate.new({ height: 6, width: 18, terminal_height: 12 })
209
+ coordinate.top.must_equal(3)
210
+ end
211
+
212
+ it 'centred is true and with default terminal height' do
213
+ console = IO.console
214
+ console.stub :winsize, [25, 80] do
215
+ coordinate = Coordinate.new({ height: 6, width: 18 })
216
+ coordinate.top.must_equal(9)
217
+ end
218
+ end
219
+
220
+ it 'centred is false' do
221
+ coordinate = Coordinate.new({ height: 6, width: 18, centred: false })
222
+ coordinate.top.must_equal(1)
223
+ end
224
+
225
+ it 'centred is false and y is set' do
226
+ coordinate = Coordinate.new({ height: 6, width: 18, y: 4, centred: false })
227
+ coordinate.top.must_equal(4)
228
+ end
229
+ end
230
+
231
+ describe '#left' do
232
+ it 'centred is true and terminal width is set' do
233
+ coordinate = Coordinate.new({ height: 6, width: 18, terminal_width: 40 })
234
+ coordinate.left.must_equal(11)
235
+ end
236
+
237
+ it 'centred is true and with default terminal width' do
238
+ console = IO.console
239
+ console.stub :winsize, [25, 80] do
240
+ coordinate = Coordinate.new({ height: 6, width: 18 })
241
+ coordinate.left.must_equal(31)
242
+ end
243
+ end
244
+
245
+ it 'centred is false' do
246
+ coordinate = Coordinate.new({ height: 6, width: 18, centred: false })
247
+ coordinate.left.must_equal(1)
248
+ end
249
+
250
+ it 'centred is false and x is set' do
251
+ coordinate = Coordinate.new({ height: 6, width: 18, x: 5, centred: false })
252
+ coordinate.left.must_equal(5)
253
+ end
254
+ end
255
+
256
+ describe '#bottom' do
257
+ it 'centred is true and terminal height is set' do
258
+ coordinate = Coordinate.new({ height: 6, width: 18, terminal_height: 12 })
259
+ coordinate.bottom.must_equal(9)
260
+ end
261
+
262
+ it 'centred is true and with default terminal height' do
263
+ console = IO.console
264
+ console.stub :winsize, [25, 80] do
265
+ coordinate = Coordinate.new({ height: 6, width: 18 })
266
+ coordinate.bottom.must_equal(15)
267
+ end
268
+ end
269
+
270
+ it 'centred is false' do
271
+ coordinate = Coordinate.new({ height: 6, width: 18, centred: false })
272
+ coordinate.bottom.must_equal(7)
273
+ end
274
+
275
+ it 'centred is false and y is set' do
276
+ coordinate = Coordinate.new({ height: 6, width: 18, y: 5, centred: false })
277
+ coordinate.bottom.must_equal(11)
278
+ end
279
+ end
280
+
281
+ describe '#right' do
282
+ it 'centred is true and terminal width is set' do
283
+ coordinate = Coordinate.new({ height: 6, width: 18, terminal_width: 40 })
284
+ coordinate.right.must_equal(29)
285
+ end
286
+
287
+ it 'centred is true and with default terminal width' do
288
+ console = IO.console
289
+ console.stub :winsize, [25, 80] do
290
+ coordinate = Coordinate.new({ height: 6, width: 18 })
291
+ coordinate.right.must_equal(49)
292
+ end
293
+ end
294
+
295
+ it 'centred is false' do
296
+ coordinate = Coordinate.new({ height: 6, width: 18, centred: false })
297
+ coordinate.right.must_equal(19)
298
+ end
299
+
300
+ it 'centred is false and x is set' do
301
+ coordinate = Coordinate.new({ height: 6, width: 18, x: 5, centred: false })
302
+ coordinate.right.must_equal(23)
303
+ end
304
+ end
305
+
306
+ describe '#position' do
307
+ it 'centred is true' do
308
+ console = IO.console
309
+ console.stub :winsize, [25, 80] do
310
+ coordinate = Coordinate.new({ height: 6, width: 18 })
311
+ coordinate.position.must_equal({
312
+ y: 9,
313
+ x: 31,
314
+ height: 6,
315
+ width: 18,
316
+ centred: true,
317
+ bottom: 15,
318
+ right: 49,
319
+ })
320
+ end
321
+ end
322
+
323
+ it 'centred is false and x is set' do
324
+ coordinate = Coordinate.new({ height: 6, width: 18, x: 7, centred: false })
325
+ coordinate.position.must_equal({
326
+ y: 1,
327
+ x: 7,
328
+ height: 6,
329
+ width: 18,
330
+ centred: false,
331
+ bottom: 7,
332
+ right: 25,
333
+ })
334
+ end
335
+
336
+ it 'centred is false and y is set' do
337
+ coordinate = Coordinate.new({ height: 6, width: 18, y: 5, centred: false })
338
+ coordinate.position.must_equal({
339
+ y: 5,
340
+ x: 1,
341
+ height: 6,
342
+ width: 18,
343
+ centred: false,
344
+ bottom: 11,
345
+ right: 19,
346
+ })
347
+ end
348
+
349
+ it 'centred is false' do
350
+ coordinate = Coordinate.new({ height: 6, width: 18, centred: false })
351
+ coordinate.position.must_equal({
352
+ y: 1,
353
+ x: 1,
354
+ height: 6,
355
+ width: 18,
356
+ centred: false,
357
+ bottom: 7,
358
+ right: 19,
359
+ })
360
+ end
361
+ end
362
+ end
363
+ end