tty-prompt 0.1.0 → 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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -2
  3. data/CHANGELOG.md +12 -0
  4. data/README.md +223 -59
  5. data/lib/tty/prompt/choice.rb +83 -0
  6. data/lib/tty/prompt/choices.rb +92 -0
  7. data/lib/tty/prompt/codes.rb +32 -0
  8. data/lib/tty/prompt/cursor.rb +131 -0
  9. data/lib/tty/prompt/list.rb +209 -0
  10. data/lib/tty/prompt/mode/echo.rb +10 -9
  11. data/lib/tty/prompt/mode/raw.rb +10 -9
  12. data/lib/tty/prompt/multi_list.rb +105 -0
  13. data/lib/tty/prompt/question/validation.rb +12 -27
  14. data/lib/tty/prompt/question.rb +58 -107
  15. data/lib/tty/prompt/reader.rb +44 -11
  16. data/lib/tty/prompt/response.rb +31 -36
  17. data/lib/tty/prompt/response_delegation.rb +3 -2
  18. data/lib/tty/prompt/statement.rb +10 -10
  19. data/lib/tty/prompt/test.rb +15 -0
  20. data/lib/tty/prompt/version.rb +3 -3
  21. data/lib/tty/prompt.rb +72 -9
  22. data/lib/tty-prompt.rb +11 -0
  23. data/spec/unit/ask_spec.rb +32 -35
  24. data/spec/unit/choice/eql_spec.rb +24 -0
  25. data/spec/unit/choice/from_spec.rb +25 -0
  26. data/spec/unit/choices/add_spec.rb +14 -0
  27. data/spec/unit/choices/each_spec.rb +15 -0
  28. data/spec/unit/choices/new_spec.rb +12 -0
  29. data/spec/unit/choices/pluck_spec.rb +11 -0
  30. data/spec/unit/cursor/new_spec.rb +74 -0
  31. data/spec/unit/error_spec.rb +4 -8
  32. data/spec/unit/multi_select_spec.rb +163 -0
  33. data/spec/unit/question/character_spec.rb +5 -16
  34. data/spec/unit/question/default_spec.rb +4 -10
  35. data/spec/unit/question/in_spec.rb +15 -12
  36. data/spec/unit/question/initialize_spec.rb +1 -6
  37. data/spec/unit/question/modify_spec.rb +25 -24
  38. data/spec/unit/question/required_spec.rb +31 -0
  39. data/spec/unit/question/validate_spec.rb +25 -17
  40. data/spec/unit/question/validation/call_spec.rb +22 -0
  41. data/spec/unit/response/read_bool_spec.rb +38 -27
  42. data/spec/unit/response/read_char_spec.rb +5 -8
  43. data/spec/unit/response/read_date_spec.rb +8 -12
  44. data/spec/unit/response/read_email_spec.rb +25 -22
  45. data/spec/unit/response/read_multiple_spec.rb +11 -13
  46. data/spec/unit/response/read_number_spec.rb +12 -16
  47. data/spec/unit/response/read_range_spec.rb +10 -13
  48. data/spec/unit/response/read_spec.rb +39 -38
  49. data/spec/unit/response/read_string_spec.rb +7 -12
  50. data/spec/unit/say_spec.rb +10 -14
  51. data/spec/unit/select_spec.rb +192 -0
  52. data/spec/unit/statement/initialize_spec.rb +0 -4
  53. data/spec/unit/suggest_spec.rb +6 -9
  54. data/spec/unit/warn_spec.rb +4 -8
  55. metadata +32 -8
  56. data/spec/unit/question/argument_spec.rb +0 -30
  57. data/spec/unit/question/valid_spec.rb +0 -46
  58. data/spec/unit/question/validation/valid_value_spec.rb +0 -22
data/lib/tty/prompt.rb CHANGED
@@ -20,12 +20,12 @@ module TTY
20
20
  # @api private
21
21
  attr_reader :output
22
22
 
23
- # Shell prompt prefix
23
+ # Prompt prefix
24
24
  #
25
25
  # @api private
26
26
  attr_reader :prefix
27
27
 
28
- # Initialize a Shell
28
+ # Initialize a Prompt
29
29
  #
30
30
  # @api public
31
31
  def initialize(input = stdin, output = stdout, options = {})
@@ -37,7 +37,7 @@ module TTY
37
37
  # Ask a question.
38
38
  #
39
39
  # @example
40
- # shell = TTY::Shell.new
40
+ # shell = TTY::Prompt.new
41
41
  # shell.ask("What is your name?")
42
42
  #
43
43
  # @param [String] statement
@@ -51,22 +51,85 @@ module TTY
51
51
  # @return [TTY::Question]
52
52
  #
53
53
  # @api public
54
- def ask(statement, *args, &block)
54
+ def ask(message, *args, &block)
55
55
  options = Utils.extract_options!(args)
56
56
 
57
- question = Question.new self, options
58
- question.instance_eval(&block) if block_given?
59
- question.prompt(statement)
57
+ question = Question.new(self, options)
58
+ question.call(message, &block)
59
+ end
60
+
61
+ # Ask a question with a list of options
62
+ #
63
+ # @example
64
+ # prompt = TTY::Prompt.new
65
+ # prompt.select("What size?", %w(large medium small))
66
+ #
67
+ # @example
68
+ # prompt = TTY::Prompt.new
69
+ # prompt.select("What size?") do |menu|
70
+ # menu.choice :large
71
+ # menu.choices %w(:medium :small)
72
+ # end
73
+ #
74
+ # @param [String] question
75
+ # the question to ask
76
+ #
77
+ # @param [Array[Object]] choices
78
+ # the choices to select from
79
+ #
80
+ # @api public
81
+ def select(question, *args, &block)
82
+ options = Utils.extract_options!(args)
83
+ choices = if block
84
+ []
85
+ elsif args.empty?
86
+ options
87
+ else
88
+ args.flatten
89
+ end
90
+
91
+ list = List.new(self, options)
92
+ list.call(question, choices, &block)
93
+ end
94
+
95
+ # Ask a question with multiple attributes activated
96
+ #
97
+ # @example
98
+ # prompt = TTY::Prompt.new
99
+ # choices = %w(Scorpion Jax Kitana Baraka Jade)
100
+ # prompt.multi_select("Choose your destiny?", choices)
101
+ #
102
+ # @param [String] question
103
+ # the question to ask
104
+ #
105
+ # @param [Array[Object]] choices
106
+ # the choices to select from
107
+ #
108
+ # @return [String]
109
+ #
110
+ # @api public
111
+ def multi_select(question, *args, &block)
112
+ options = Utils.extract_options!(args)
113
+ choices = if block
114
+ []
115
+ elsif args.empty?
116
+ options
117
+ else
118
+ args.flatten
119
+ end
120
+
121
+ list = MultiList.new(self, options)
122
+ list.call(question, choices, &block)
60
123
  end
61
124
 
62
125
  # A shortcut method to ask the user positive question and return
63
- # true for 'yes' reply.
126
+ # true for 'yes' reply, false for 'no'.
64
127
  #
65
128
  # @return [Boolean]
66
129
  #
67
130
  # @api public
68
131
  def yes?(statement, *args, &block)
69
- ask(statement, *args, &block).read_bool
132
+ ask(statement, {read: :bool}, &block)
70
133
  end
71
134
 
72
135
  # A shortcut method to ask the user negative question and return
data/lib/tty-prompt.rb CHANGED
@@ -5,11 +5,22 @@ require 'pastel'
5
5
  require 'tty-platform'
6
6
 
7
7
  require 'tty/prompt'
8
+ require 'tty/prompt/choice'
9
+ require 'tty/prompt/choices'
10
+ require 'tty/prompt/codes'
11
+ require 'tty/prompt/cursor'
12
+ require 'tty/prompt/list'
13
+ require 'tty/prompt/multi_list'
8
14
  require 'tty/prompt/mode'
9
15
  require 'tty/prompt/question'
10
16
  require 'tty/prompt/reader'
11
17
  require 'tty/prompt/response'
12
18
  require 'tty/prompt/statement'
13
19
  require 'tty/prompt/suggestion'
20
+ require 'tty/prompt/test'
14
21
  require 'tty/prompt/utils'
15
22
  require 'tty/prompt/version'
23
+
24
+ module TTY
25
+ PromptConfigurationError = Class.new(StandardError)
26
+ end
@@ -3,74 +3,71 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe TTY::Prompt, '#ask' do
6
- let(:input) { StringIO.new }
7
- let(:output) { StringIO.new }
8
- let(:prefix) { '' }
9
- let(:options) { { prefix: prefix } }
10
6
 
11
- subject(:prompt) { TTY::Prompt.new(input, output, options) }
7
+ subject(:prompt) { TTY::TestPrompt.new }
12
8
 
13
9
  it 'prints message' do
14
- prompt.ask "What is your name?"
15
- expect(output.string).to eql "What is your name?\n"
10
+ prompt.ask("What is your name?")
11
+ expect(prompt.output.string).to eql("What is your name?")
16
12
  end
17
13
 
18
14
  it 'prints an empty message ' do
19
- prompt.ask ""
20
- expect(output.string).to eql ""
15
+ prompt.ask('')
16
+ expect(prompt.output.string).to eql('')
21
17
  end
22
18
 
23
19
  it 'prints an empty message and returns nil if EOF is sent to stdin' do
24
- input << nil
25
- input.rewind
26
- q = prompt.ask ""
27
- expect(q.read).to eql nil
20
+ prompt.input << nil
21
+ prompt.input.rewind
22
+ response = prompt.ask("")
23
+ expect(response).to eql(nil)
24
+ expect(prompt.output.string).to eq('')
28
25
  end
29
26
 
30
- context 'with a prompt prefix' do
31
- let(:prefix) { ' > ' }
32
-
33
- it "asks a question with '>'" do
34
- input << ''
35
- input.rewind
36
- prompt.ask "Are you Polish?"
37
- expect(output.string).to eql " > Are you Polish?\n"
38
- end
27
+ it "asks a question with a prefix '>'" do
28
+ prompt = TTY::TestPrompt.new(prefix: ' > ')
29
+ prompt.input << ''
30
+ prompt.input.rewind
31
+ response = prompt.ask "Are you Polish?"
32
+ expect(response).to eq(nil)
33
+ expect(prompt.output.string).to eql " > Are you Polish?"
39
34
  end
40
35
 
41
36
  it 'asks a question with block' do
42
- input << ''
43
- input.rewind
44
- q = prompt.ask "What is your name?" do
45
- default 'Piotr'
37
+ prompt.input << ''
38
+ prompt.input.rewind
39
+ value = prompt.ask "What is your name?" do |q|
40
+ q.default 'Piotr'
46
41
  end
47
- expect(q.read).to eql "Piotr"
42
+ expect(value).to eql "Piotr"
43
+ expect(prompt.output.string).to eq('What is your name?')
48
44
  end
49
45
 
50
46
  context 'yes?' do
51
47
  it 'agrees' do
52
- input << 'yes'
53
- input.rewind
48
+ prompt.input << 'yes'
49
+ prompt.input.rewind
54
50
  expect(prompt.yes?("Are you a human?")).to eq(true)
51
+ expect(prompt.output.string).to eq('Are you a human?')
55
52
  end
56
53
 
57
54
  it 'disagrees' do
58
- input << 'no'
59
- input.rewind
55
+ prompt.input << 'no'
56
+ prompt.input.rewind
60
57
  expect(prompt.yes?("Are you a human?")).to eq(false)
61
58
  end
62
59
  end
63
60
 
64
61
  context 'no?' do
65
62
  it 'agrees' do
66
- input << 'no'
67
- input.rewind
63
+ prompt.input << 'no'
64
+ prompt.input.rewind
68
65
  expect(prompt.no?("Are you a human?")).to eq(true)
69
66
  end
70
67
 
71
68
  it 'disagrees' do
72
- input << 'yes'
73
- input.rewind
69
+ prompt.input << 'yes'
70
+ prompt.input.rewind
74
71
  expect(prompt.no?("Are you a human?")).to eq(false)
75
72
  end
76
73
  end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::Prompt::Choice, '#==' do
6
+ it "is true with the same name and value attributes" do
7
+ expect(described_class.new(:large, 1)).
8
+ to eq(described_class.new(:large, 1))
9
+ end
10
+
11
+ it "is false with different name attribute" do
12
+ expect(described_class.new(:large, 1)).
13
+ not_to eq(described_class.new(:medium, 1))
14
+ end
15
+
16
+ it "is false with different value attribute" do
17
+ expect(described_class.new(:large, 1)).
18
+ not_to eq(described_class.new(:large, 2))
19
+ end
20
+
21
+ it "is false with non-choice object" do
22
+ expect(described_class.new(:large, 1)).not_to eq(:other)
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::Prompt::Choice, '#from' do
6
+ it "creates choice from choice" do
7
+ choice = described_class.new(:large, 1)
8
+ expect(described_class.from(choice)).to eq(choice)
9
+ end
10
+
11
+ it "creates choice from string" do
12
+ choice = described_class.new('large', 'large')
13
+ expect(described_class.from('large')).to eq(choice)
14
+ end
15
+
16
+ it "creates choice from array" do
17
+ choice = described_class.new('large', 1)
18
+ expect(described_class.from([:large, 1])).to eq(choice)
19
+ end
20
+
21
+ it "creates choice from hash value" do
22
+ choice = described_class.new('large', 1)
23
+ expect(described_class.from({large: 1})).to eq(choice)
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::Prompt::Choices, '#<<' do
6
+ it "adds choice to collection" do
7
+ choices = described_class.new
8
+ expect(choices).to be_empty
9
+ choice = TTY::Prompt::Choice.from([:label, 1])
10
+ choices << [:label, 1]
11
+ expect(choices.size).to eq(1)
12
+ expect(choices.to_ary).to eq([choice])
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::Prompt::Choices, '.each' do
6
+ it "iterates over collection" do
7
+ choices = described_class[:large, :medium, :small]
8
+ actual = []
9
+ choices.each do |choice|
10
+ actual << choice.name
11
+ end
12
+ expect(actual).to eq([:large, :medium, :small])
13
+ expect(choices.each).to be_kind_of(Enumerator)
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::Prompt::Choices, '.new' do
6
+ it "creates choices collection" do
7
+ choice_1 = TTY::Prompt::Choice.from(:label1)
8
+ choice_2 = TTY::Prompt::Choice.from(:label2)
9
+ collection = described_class[:label1, :label2]
10
+ expect(collection.choices).to eq([choice_1, choice_2])
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::Prompt::Choices, '.pluck' do
6
+ it "plucks choice from collection by name" do
7
+ collection = %w(large medium small)
8
+ choices = described_class[*collection]
9
+ expect(choices.pluck('medium').name).to eq('medium')
10
+ end
11
+ end
@@ -0,0 +1,74 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::Prompt::Cursor do
6
+ it "allows to print without mutating state" do
7
+ cursor = described_class.new
8
+ expect(cursor.shell).to eq(false)
9
+ expect(cursor.print.shell).to eq(true)
10
+ expect(cursor.shell).to eq(false)
11
+ end
12
+
13
+ it "shows cursor" do
14
+ cursor = described_class.new
15
+ expect(cursor.show).to eq("\e[?25h")
16
+ end
17
+
18
+ it "hides cursor" do
19
+ cursor = described_class.new
20
+ expect(cursor.hide).to eq("\e[?25l")
21
+ end
22
+
23
+ it "saves cursor position" do
24
+ cursor = described_class.new
25
+ expect(cursor.save).to eq("\e[s")
26
+ end
27
+
28
+ it "restores cursor position" do
29
+ cursor = described_class.new
30
+ expect(cursor.restore).to eq("\e[u")
31
+ end
32
+
33
+ it "moves up default by 1 line" do
34
+ cursor = described_class.new
35
+ expect(cursor.move_up).to eq("\e[1A")
36
+ end
37
+
38
+ it "moves up by 5 lines" do
39
+ cursor = described_class.new
40
+ expect(cursor.move_up(5)).to eq("\e[5A")
41
+ end
42
+
43
+ it "moves down default by 1 line" do
44
+ cursor = described_class.new
45
+ expect(cursor.move_down).to eq("\e[1B")
46
+ end
47
+
48
+ it "clears line" do
49
+ cursor = described_class.new
50
+ expect(cursor.clear_line).to eq("\e[1000D\e[K")
51
+ end
52
+
53
+ it "clears 5 lines up" do
54
+ cursor = described_class.new
55
+ expect(cursor.clear_lines(5)).to eq([
56
+ "\e[1A\e[1000D\e[K",
57
+ "\e[1A\e[1000D\e[K",
58
+ "\e[1A\e[1000D\e[K",
59
+ "\e[1A\e[1000D\e[K",
60
+ "\e[1A\e[1000D\e[K"
61
+ ].join)
62
+ end
63
+
64
+ it "clears 5 lines down" do
65
+ cursor = described_class.new
66
+ expect(cursor.clear_lines(5, :down)).to eq([
67
+ "\e[1B\e[1000D\e[K",
68
+ "\e[1B\e[1000D\e[K",
69
+ "\e[1B\e[1000D\e[K",
70
+ "\e[1B\e[1000D\e[K",
71
+ "\e[1B\e[1000D\e[K"
72
+ ].join)
73
+ end
74
+ end
@@ -3,28 +3,24 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe TTY::Prompt, '.error' do
6
- let(:input) { StringIO.new }
7
- let(:output) { StringIO.new }
8
6
  let(:color) { Pastel.new(enabled: true) }
9
7
 
10
- subject(:prompt) { described_class.new(input, output) }
8
+ subject(:prompt) { TTY::TestPrompt.new }
11
9
 
12
10
  before { allow(Pastel).to receive(:new).and_return(color) }
13
11
 
14
- after { output.rewind }
15
-
16
12
  it 'displays one message' do
17
13
  prompt.error "Nothing is fine!"
18
- expect(output.string).to eql "\e[31mNothing is fine!\e[0m\n"
14
+ expect(prompt.output.string).to eql "\e[31mNothing is fine!\e[0m\n"
19
15
  end
20
16
 
21
17
  it 'displays many messages' do
22
18
  prompt.error "Nothing is fine!", "All is broken!"
23
- expect(output.string).to eql "\e[31mNothing is fine!\e[0m\n\e[31mAll is broken!\e[0m\n"
19
+ expect(prompt.output.string).to eql "\e[31mNothing is fine!\e[0m\n\e[31mAll is broken!\e[0m\n"
24
20
  end
25
21
 
26
22
  it 'displays message with option' do
27
23
  prompt.error "Nothing is fine!", newline: false
28
- expect(output.string).to eql "\e[31mNothing is fine!\e[0m"
24
+ expect(prompt.output.string).to eql "\e[31mNothing is fine!\e[0m"
29
25
  end
30
26
  end
@@ -0,0 +1,163 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::Prompt do
6
+ let(:color) { Pastel.new(enabled: true) }
7
+
8
+ before { allow(Pastel).to receive(:new).and_return(color) }
9
+
10
+ it "selects nothing when return pressed immediately" do
11
+ prompt = TTY::TestPrompt.new
12
+ choices = %w(vodka beer wine whisky bourbon)
13
+ prompt.input << "\r"
14
+ prompt.input.rewind
15
+ expect(prompt.multi_select("Select drinks?", choices)). to eq([])
16
+ expect(prompt.output.string).to eq([
17
+ "\e[?25lSelect drinks? \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
18
+ "‣ ⬡ vodka\n",
19
+ " ⬡ beer\n",
20
+ " ⬡ wine\n",
21
+ " ⬡ whisky\n",
22
+ " ⬡ bourbon\n",
23
+ "\e[1A\e[1000D\e[K" * 6,
24
+ "Select drinks? \n\e[?25h"
25
+ ].join)
26
+ end
27
+
28
+ it "selects item when space pressed" do
29
+ prompt = TTY::TestPrompt.new
30
+ choices = %w(vodka beer wine whisky bourbon)
31
+ prompt.input << " \r"
32
+ prompt.input.rewind
33
+ expect(prompt.multi_select("Select drinks?", choices)). to eq(['vodka'])
34
+ expect(prompt.output.string).to eq([
35
+ "\e[?25lSelect drinks? \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
36
+ "‣ ⬡ vodka\n",
37
+ " ⬡ beer\n",
38
+ " ⬡ wine\n",
39
+ " ⬡ whisky\n",
40
+ " ⬡ bourbon\n",
41
+ "\e[1A\e[1000D\e[K" * 6,
42
+ "Select drinks? vodka\n",
43
+ "‣ \e[32m⬢\e[0m vodka\n",
44
+ " ⬡ beer\n",
45
+ " ⬡ wine\n",
46
+ " ⬡ whisky\n",
47
+ " ⬡ bourbon\n",
48
+ "\e[1A\e[1000D\e[K" * 6,
49
+ "Select drinks? \e[32mvodka\e[0m\n\e[?25h"
50
+ ].join)
51
+ end
52
+
53
+ it "sets choice custom values" do
54
+ prompt = TTY::TestPrompt.new
55
+ choices = {vodka: 1, beer: 2, wine: 3, whisky: 4, bourbon: 5}
56
+ prompt.input << " \r"
57
+ prompt.input.rewind
58
+ expect(prompt.multi_select("Select drinks?", choices)).to eq([1])
59
+ expect(prompt.output.string).to eq([
60
+ "\e[?25lSelect drinks? \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
61
+ "‣ ⬡ vodka\n",
62
+ " ⬡ beer\n",
63
+ " ⬡ wine\n",
64
+ " ⬡ whisky\n",
65
+ " ⬡ bourbon\n",
66
+ "\e[1A\e[1000D\e[K" * 6,
67
+ "Select drinks? vodka\n",
68
+ "‣ \e[32m⬢\e[0m vodka\n",
69
+ " ⬡ beer\n",
70
+ " ⬡ wine\n",
71
+ " ⬡ whisky\n",
72
+ " ⬡ bourbon\n",
73
+ "\e[1A\e[1000D\e[K" * 6,
74
+ "Select drinks? \e[32mvodka\e[0m\n\e[?25h"
75
+ ].join)
76
+ end
77
+
78
+ it "sets choice name and value through DSL" do
79
+ prompt = TTY::TestPrompt.new
80
+ prompt.input << " \r"
81
+ prompt.input.rewind
82
+ value = prompt.multi_select("Select drinks?") do |menu|
83
+ menu.choice :vodka, {score: 1}
84
+ menu.choice :beer, 2
85
+ menu.choice :wine, 3
86
+ menu.choices whisky: 4, bourbon: 5
87
+ end
88
+ expect(value).to eq([{score: 1}])
89
+ expect(prompt.output.string).to eq([
90
+ "\e[?25lSelect drinks? \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
91
+ "‣ ⬡ vodka\n",
92
+ " ⬡ beer\n",
93
+ " ⬡ wine\n",
94
+ " ⬡ whisky\n",
95
+ " ⬡ bourbon\n",
96
+ "\e[1A\e[1000D\e[K" * 6,
97
+ "Select drinks? vodka\n",
98
+ "‣ \e[32m⬢\e[0m vodka\n",
99
+ " ⬡ beer\n",
100
+ " ⬡ wine\n",
101
+ " ⬡ whisky\n",
102
+ " ⬡ bourbon\n",
103
+ "\e[1A\e[1000D\e[K" * 6,
104
+ "Select drinks? \e[32mvodka\e[0m\n\e[?25h"
105
+ ].join)
106
+ end
107
+
108
+ it "sets default options through DSL syntax" do
109
+ prompt = TTY::TestPrompt.new
110
+ prompt.input << "\r"
111
+ prompt.input.rewind
112
+ value = prompt.multi_select("Select drinks?") do |menu|
113
+ menu.default 2, 5
114
+
115
+ menu.choice :vodka, {score: 10}
116
+ menu.choice :beer, {score: 20}
117
+ menu.choice :wine, {score: 30}
118
+ menu.choice :whisky, {score: 40}
119
+ menu.choice :bourbon, {score: 50}
120
+ end
121
+ expect(value).to match_array([{score: 20}, {score: 50}])
122
+ expect(prompt.output.string).to eq([
123
+ "\e[?25lSelect drinks? beer, bourbon\n",
124
+ " ⬡ vodka\n",
125
+ " \e[32m⬢\e[0m beer\n",
126
+ " ⬡ wine\n",
127
+ " ⬡ whisky\n",
128
+ "‣ \e[32m⬢\e[0m bourbon\n",
129
+ "\e[1A\e[1000D\e[K" * 6,
130
+ "Select drinks? \e[32mbeer, bourbon\e[0m\n\e[?25h",
131
+ ].join)
132
+ end
133
+
134
+ it "sets default options through hash syntax" do
135
+ prompt = TTY::TestPrompt.new
136
+ prompt.input << "\r"
137
+ prompt.input.rewind
138
+ value = prompt.multi_select("Select drinks?",default: [2, 5]) do |menu|
139
+ menu.choice :vodka, {score: 10}
140
+ menu.choice :beer, {score: 20}
141
+ menu.choice :wine, {score: 30}
142
+ menu.choice :whisky, {score: 40}
143
+ menu.choice :bourbon, {score: 50}
144
+ end
145
+ expect(value).to match_array([{score: 20}, {score: 50}])
146
+ end
147
+
148
+ it "raises error for defaults out of range" do
149
+ prompt = TTY::TestPrompt.new
150
+ prompt.input << "\r"
151
+ prompt.input.rewind
152
+ expect {
153
+ prompt.multi_select("Select drinks?",default: [2, 6]) do |menu|
154
+ menu.choice :vodka, {score: 10}
155
+ menu.choice :beer, {score: 20}
156
+ menu.choice :wine, {score: 30}
157
+ menu.choice :whisky, {score: 40}
158
+ menu.choice :bourbon, {score: 50}
159
+ end
160
+ }.to raise_error(TTY::PromptConfigurationError,
161
+ /default index `6` out of range \(1 - 5\)/)
162
+ end
163
+ end
@@ -3,22 +3,11 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe TTY::Prompt::Question, '#character' do
6
- let(:input) { StringIO.new }
7
- let(:output) { StringIO.new }
8
- let(:prompt) { TTY::Prompt.new(input, output) }
9
-
10
6
  it 'switches to character input' do
11
- input << "abcd"
12
- input.rewind
13
- q = prompt.ask("Which one do you prefer a, b, c or d?").char(true)
14
- expect(q.character)
15
- expect(q.read_string).to eq("abcd")
16
- end
17
-
18
- it 'acts as reader without arguments' do
19
- input << "abcd"
20
- input.rewind
21
- q = prompt.ask("Which one do you prefer a, b, c or d?")
22
- expect(q.char).to eq(false)
7
+ prompt = TTY::TestPrompt.new
8
+ prompt.input << "abcd"
9
+ prompt.input.rewind
10
+ answer = prompt.ask("Which one do you prefer a, b, c or d?") { |q| q.char(true) }
11
+ expect(answer).to eq("abcd")
23
12
  end
24
13
  end
@@ -3,23 +3,17 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe TTY::Prompt::Question, '#default' do
6
- let(:input) { StringIO.new }
7
- let(:output) { StringIO.new }
8
- let(:prompt) { TTY::Prompt.new(input, output) }
9
-
10
6
  it 'uses default value' do
7
+ prompt = TTY::TestPrompt.new
11
8
  name = 'Anonymous'
12
- q = prompt.ask("What is your name?").default(name)
13
- answer = q.read
9
+ answer = prompt.ask('What is your name?', default: name)
14
10
  expect(answer).to eq(name)
15
11
  end
16
12
 
17
13
  it 'uses default value in block' do
14
+ prompt = TTY::TestPrompt.new
18
15
  name = 'Anonymous'
19
- q = prompt.ask "What is your name?" do
20
- default name
21
- end
22
- answer = q.read
16
+ answer = prompt.ask('What is your name?') { |q| q.default(name) }
23
17
  expect(answer).to eq(name)
24
18
  end
25
19
  end