urban 0.1.3 → 1.0.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.
@@ -0,0 +1,57 @@
1
+ class MiniTest::StopLight
2
+ ESC = "\e["
3
+ NND = "#{ESC}0m"
4
+
5
+ attr_reader :io
6
+
7
+ def initialize io
8
+ @io = io
9
+ end
10
+
11
+ def red str
12
+ normal_color(31, str)
13
+ end
14
+
15
+ def yellow str
16
+ normal_color(33, str)
17
+ end
18
+
19
+ def green str
20
+ normal_color(32, str)
21
+ end
22
+
23
+ def normal_color(color_code, str)
24
+ "#{ESC}#{color_code}m#{str}#{NND}"
25
+ end
26
+
27
+ def print(o)
28
+ case o
29
+ when '.'; io.print green(o)
30
+ when 'E', 'F'; io.print red(o)
31
+ when 'S'; io.print yellow(o)
32
+ else; io.print o
33
+ end
34
+ end
35
+
36
+ def puts(*o)
37
+ o.map! do |str|
38
+ case str
39
+ when /Failure:/, /Error:/, /[1-9]+ failures/, /[1-9]+ errors/;
40
+ red(str)
41
+ when /Skipped:/
42
+ yellow(str)
43
+ when /0 failures, 0 errors/;
44
+ green(str).gsub(/([1-9]+ skips)/, yellow('\1'))
45
+ else;
46
+ str.gsub(/([1-9]+ skips)/, yellow('\1'))
47
+ end
48
+ end
49
+ super
50
+ end
51
+
52
+ def method_missing(msg, *args)
53
+ io.send(msg, *args)
54
+ end
55
+ end
56
+
57
+ MiniTest::Unit.output = MiniTest::StopLight.new(MiniTest::Unit.output)
@@ -1,34 +1,28 @@
1
1
  $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
2
2
 
3
3
  require 'rubygems'
4
+ gem 'minitest' if RUBY_VERSION > '1.9'
4
5
  require 'minitest/autorun'
5
6
  require 'urban'
6
7
  require 'urban/cli'
8
+ require 'minitest/stop_light'
9
+ require 'ostruct'
7
10
 
8
- TEST_PHRASE = OpenStruct.new({
9
- :word => 'impromptu',
10
- :definitions => [
11
- 'Something that is made up on the spot and given little time to gather and present. Usually referring to speeches that are given only a few minutes to prepare for.',
11
+ TEST_ENTRY = Urban::Dictionary::Entry.new('impromptu',
12
+ [ 'Something that is made up on the spot and given little time to gather and present. Usually referring to speeches that are given only a few minutes to prepare for.',
12
13
  'On the spot',
13
- 'Something that is made up on the spot. Can also mean a speech that was made with little or no preparation.'
14
- ]})
14
+ 'Something that is made up on the spot. Can also mean a speech that was made with little or no preparation.' ],
15
+ 'http://www.urbandictionary.com/define.php?term=impromptu')
16
+
17
+ EMPTY_ENTRY = Urban::Dictionary::Entry.new('gubble', nil, nil)
15
18
 
16
19
  def load_file(filename)
17
20
  IO.read(File.expand_path("../data/#{filename}", __FILE__))
18
21
  end
19
22
 
20
- ['refute', 'assert'].each do |action|
21
- eval <<-EOM
22
- def #{action}_cli_prints(matches, &block)
23
- out, err = capture_io(&block)
24
- [*matches].each { |match| #{action}_match(match, out) }
25
- end
26
- EOM
27
- end
28
-
29
23
  module Stub
30
24
  def stub(name, &block)
31
- self.class.send(:remove_method, name) if respond_to?(name)
32
- self.class.send(:define_method, name, &block)
25
+ singleton_class = class << self; self; end
26
+ singleton_class.send(:define_method, name, &block)
33
27
  end
34
28
  end
@@ -1,101 +1,212 @@
1
1
  require 'test_helper'
2
+ require 'open-uri'
3
+ require 'socket'
4
+ require 'shellwords'
2
5
 
3
6
  class CLITest < MiniTest::Unit::TestCase
4
7
 
8
+ HELP_SCREEN = <<-EOS
9
+ Usage: urban [OPTION]... [PHRASE]
10
+ Search http://urbandictionary.com for definitions of phrases
11
+
12
+ Options:
13
+ -a, --all List all definitions
14
+ -r, --random Return a random phrase and definition
15
+ -u, --url Print the definition's url after the definition
16
+ -h, --help Show this message
17
+ -v, --version Show version information
18
+ -l, --list DEPRECATED please use --all or -a instead
19
+
20
+ Examples:
21
+ urban cookie monster Search for "cookie monster" and print its
22
+ first definition
23
+ urban -a cookie monster Search for "cookie monster" and print all of
24
+ its available definitions
25
+ urban -r Print a random phrase and its first definition
26
+ urban -ra Print a random phrase and all of its available
27
+ definitions
28
+
29
+ EOS
30
+
5
31
  def setup
6
32
  @program = Urban::CLI.new
7
33
  end
8
34
 
9
- def test_parse_prints_help
10
- expectations = [
11
- /Usage: urban \[OPTION\]\.\.\. \[PHRASE\]/,
12
- /Search http:\/\/urbandictionary\.com for definitions/,
13
- /-l, --list\s*List all definitions/,
14
- /-r, --random\s*Find random word on urban dictionary/,
15
- /-h, --help\s*Show this message/,
16
- /-version\s*Show version/
17
- ]
18
- assert_cli_prints(expectations) { @program.run(["-h"]) }
35
+ # Helpers
36
+ def assert_program_output(argument_variations, stdout=nil, stderr=nil)
37
+ argument_variations.each do |args|
38
+ assert_output(stdout, stderr) { @program.run(Shellwords.shellwords(args)) }
39
+ end
19
40
  end
20
41
 
21
- def test_parse_prints_version_info
22
- args = ['-v']
23
- assert_cli_prints(/^Urban \d+\.\d+\.\d+ \(c\) Thomas Miller$/) { @program.run(args) }
24
- end
42
+ class CLIArgumentParsingTest < CLITest
25
43
 
26
- def test_no_args_prints_help
27
- args = []
28
- assert_cli_prints(/Usage: urban \[OPTION\]\.\.\. \[PHRASE\]/) { @program.run(args) }
29
- end
44
+ # Helpers
45
+ def assert_flag_is_set(name)
46
+ ["-#{name.chars.first}", "--#{name}"].each do |args|
47
+ options = @program.send(:parse, [args])
48
+ assert_equal(true, options.send(name))
49
+ end
50
+ end
30
51
 
31
- def test_no_args_with_list_option_prints_help
32
- args = ['-l']
33
- assert_cli_prints(/Usage: urban \[OPTION\]\.\.\. \[PHRASE\]/) { @program.run(args) }
34
- end
52
+ # Tests
53
+ def test_defaults
54
+ assert_silent do
55
+ options = @program.send(:parse, [])
56
+ assert_equal(false, options.help)
57
+ assert_equal(false, options.version)
58
+ assert_equal(false, options.random)
59
+ assert_equal(false, options.all)
60
+ assert_equal('', options.phrase)
61
+ end
62
+ end
35
63
 
36
- def test_parse_returns_random
37
- capture_io do
38
- actual = @program.send(:parse, ['-r'])
39
- assert(actual.random, 'Args -r; Expected true, returned false')
40
- actual = @program.send(:parse, ['--random'])
41
- assert(actual.random, 'Args --random Expected true, returned false')
64
+ def test_phrase
65
+ assert_silent do
66
+ options = @program.send(:parse, ['foo bar'])
67
+ assert_equal('foo bar', options.phrase)
68
+ end
42
69
  end
43
- end
44
70
 
45
- def test_parse_returns_list
46
- capture_io do
47
- actual = @program.send(:parse, ['-l'])
48
- assert(actual.list, 'Args: -l; Expected true, returned false')
49
- actual = @program.send(:parse, ['--list'])
50
- assert(actual.list, 'Args: --list; Expected true, returned false')
71
+ def test_help_flag
72
+ assert_silent do
73
+ assert_flag_is_set('help')
74
+ end
51
75
  end
52
- end
53
76
 
54
- def test_parse_returns_phrase
55
- capture_io do
56
- actual = @program.send(:parse, ['Cookie', 'monster'])
57
- assert_equal('Cookie monster', actual.phrase)
58
- actual = @program.send(:parse, ['Cookie monster'])
59
- assert_equal('Cookie monster', actual.phrase)
77
+ def test_version_flag
78
+ assert_silent do
79
+ assert_flag_is_set('version')
80
+ end
81
+ end
82
+
83
+ def test_random_flag
84
+ assert_silent do
85
+ assert_flag_is_set('random')
86
+ end
87
+ end
88
+
89
+ def test_all_flag
90
+ assert_silent do
91
+ assert_flag_is_set('all')
92
+ end
93
+ end
94
+
95
+ def test_all_flag
96
+ assert_silent do
97
+ assert_flag_is_set('url')
98
+ end
60
99
  end
61
100
  end
62
101
 
63
- class CLIDefinintionOutputTest < CLITest
102
+ class CLIRunnerStandardOutputTest < CLITest
103
+
104
+ SINGLE_DEFINITION = "\n#{TEST_ENTRY.phrase.upcase}\n\n#{TEST_ENTRY.definitions.first}\n\n"
105
+ MULTIPLE_DEFINITIONS = "\n#{TEST_ENTRY.phrase.upcase}\n\n#{TEST_ENTRY.definitions.join("\n\n")}\n\n"
106
+ DEFINITION_WITH_URL = "\n#{TEST_ENTRY.phrase.upcase}\n\n#{TEST_ENTRY.definitions.first}\n\nURL: #{TEST_ENTRY.url}\n\n"
107
+
64
108
  def setup
65
- @dictionary = MiniTest::Mock.new
66
109
  super
110
+ @dictionary = MiniTest::Mock.new
111
+ end
112
+
113
+ # Tests
114
+ def test_help_flag_prints_help
115
+ assert_output(HELP_SCREEN) { @program.run([]) }
67
116
  end
68
117
 
69
- def test_cli_prints_random_definition
70
- args = ['-r']
71
- expected = [ "#{TEST_PHRASE.word.upcase}", TEST_PHRASE.definitions.first ]
72
- @program.dictionary = @dictionary.expect(:random, TEST_PHRASE)
73
- assert_cli_prints(expected) { @program.run(args) }
118
+ def test_version_flag_prints_version
119
+ ['-v', '--v'].each do |args|
120
+ assert_output("Urban #{Urban::VERSION} (c) Thomas Miller\n") { @program.run([args]) }
121
+ end
122
+ end
123
+
124
+ def test_random_flag_prints_single_definition
125
+ @program.dictionary = @dictionary.expect(:random, TEST_ENTRY)
126
+ argument_variations = ['-r', '--random']
127
+ assert_program_output(argument_variations, SINGLE_DEFINITION)
128
+ @dictionary.verify
129
+ end
130
+
131
+ def test_phrase_prints_single_definition
132
+ @program.dictionary = @dictionary.expect(:search, TEST_ENTRY, ['impromptu'])
133
+ argument_variations = ['impromptu']
134
+ assert_program_output(argument_variations, SINGLE_DEFINITION)
135
+ @dictionary.verify
136
+ end
137
+
138
+ def test_random_and_all_flag_prints_multiple_definitions
139
+ @program.dictionary = @dictionary.expect(:random, TEST_ENTRY)
140
+ argument_variations = ['-ra', '-r -a', '--random -a', '-r --all', '--all --random']
141
+ assert_program_output(argument_variations, MULTIPLE_DEFINITIONS)
74
142
  @dictionary.verify
75
143
  end
76
144
 
77
- def test_cli_prints_random_definition_list
78
- args = ['-rl']
79
- expected = [ "#{TEST_PHRASE.word.upcase}", *TEST_PHRASE.definitions ]
80
- @program.dictionary = @dictionary.expect(:random, TEST_PHRASE)
81
- assert_cli_prints(expected) { @program.run(args) }
145
+ def test_phrase_and_all_flag_prints_multiple_definitions
146
+ @program.dictionary = @dictionary.expect(:search, TEST_ENTRY, ['impromptu'])
147
+ argument_variations = ['impromptu -a', '--all impromptu']
148
+ assert_program_output(argument_variations, MULTIPLE_DEFINITIONS)
82
149
  @dictionary.verify
83
150
  end
84
151
 
85
- def test_cli_prints_definition
86
- args = ['impromptu']
87
- expected = [ "#{TEST_PHRASE.word.upcase}", TEST_PHRASE.definitions.first ]
88
- @program.dictionary = @dictionary.expect(:search, TEST_PHRASE, ['impromptu'])
89
- assert_cli_prints(expected) { @program.run(['impromptu']) }
152
+ def test_random_and_url_flag_prints_definition_with_url
153
+ @program.dictionary = @dictionary.expect(:random, TEST_ENTRY)
154
+ argument_variations = ['-ru', '-r -u', '--random -u', '-r --url', '--url --random']
155
+ assert_program_output(argument_variations, DEFINITION_WITH_URL)
90
156
  @dictionary.verify
91
157
  end
92
158
 
93
- def test_cli_prints_definition_list
94
- args = ['-l', 'impromptu']
95
- expected = [ "#{TEST_PHRASE.word.upcase}", *TEST_PHRASE.definitions ]
96
- @program.dictionary = @dictionary.expect(:search, TEST_PHRASE, ['impromptu'])
97
- assert_cli_prints(expected) { @program.run(args) }
159
+ def test_phrase_and_url_flag_prints_definition_with_url
160
+ @program.dictionary = @dictionary.expect(:search, TEST_ENTRY, ['impromptu'])
161
+ argument_variations = ['impromptu -u', '--url impromptu']
162
+ assert_program_output(argument_variations, DEFINITION_WITH_URL)
98
163
  @dictionary.verify
99
164
  end
165
+
166
+ def test_list_flag_prints_deprecation_warning
167
+ expected = /WARNING: --list and -l are deprecated please use --all or -a instead/
168
+ @program.dictionary = @dictionary.expect(:search, TEST_ENTRY, ['impromptu'])
169
+ @program.dictionary = @dictionary.expect(:random, TEST_ENTRY)
170
+ stdout, stederr = capture_io { @program.run(Shellwords.shellwords('--list impromptu')) }
171
+ assert_match expected, stdout
172
+ stdou, stederr = capture_io { @program.run(Shellwords.shellwords('-rl')) }
173
+ assert_match expected, stdout
174
+ end
175
+ end
176
+
177
+ class CLIRunnerErrorOutputTest < CLITest
178
+
179
+ ERROR_MISSING_PHRASE = "urban: no definitions found for #{EMPTY_ENTRY.phrase.upcase}.\n"
180
+ ERROR_NO_INTERNET = "urban: no internet connection available.\n"
181
+ ERROR_INVALID_OPTION = <<-EOE
182
+ urban: invalid option: -b
183
+ Try `urban --help' for more information.
184
+ EOE
185
+
186
+ def setup
187
+ super
188
+ end
189
+
190
+ # Tests
191
+ def test_search_missing_phrase_prints_error
192
+ dictionary = MiniTest::Mock.new
193
+ @program.dictionary = dictionary.expect(:search, EMPTY_ENTRY, ['gubble'])
194
+ assert_program_output(['gubble'], nil, ERROR_MISSING_PHRASE)
195
+ dictionary.verify
196
+ end
197
+
198
+ def test_search_missing_phrase_prints_error
199
+ dictionary = (Object.new).extend Stub
200
+ dictionary.stub(:search) { |phrase| raise SocketError }
201
+ @program.dictionary = dictionary
202
+ assert_program_output(['gubble'], nil, ERROR_NO_INTERNET)
203
+ end
204
+
205
+ def test_invalid_option_prints_help
206
+ dictionary = (Object.new).extend Stub
207
+ dictionary.stub(:search) { |phrase| raise OptionParser::InvalidOption }
208
+ @program.dictionary = dictionary
209
+ assert_program_output(['-b'], nil, ERROR_INVALID_OPTION)
210
+ end
100
211
  end
101
212
  end
@@ -4,18 +4,34 @@ class DictionaryTest < MiniTest::Unit::TestCase
4
4
 
5
5
  def setup
6
6
  @web_service = MiniTest::Mock.new
7
- @dictionary = Urban::Dictionary.new
7
+ @dictionary = Urban::Dictionary
8
+
9
+ @response = OpenStruct.new
10
+ @response.url = 'http://www.urbandictionary.com/define.php?term=impromptu'
11
+ @response.stream = load_file('impromptu.html')
12
+ end
13
+
14
+ def test_process_extracts_elements_from_html
15
+ entry = @dictionary.send(:process, @response )
16
+ assert_equal(TEST_ENTRY, entry)
8
17
  end
9
18
 
10
19
  def test_dictionary_calls_random
11
- @dictionary.web_service = @web_service.expect(:query, load_file('impromptu.html') ,[:random])
12
- assert_equal(TEST_PHRASE, @dictionary.random)
20
+ @dictionary.web_service = @web_service.expect(:random, @response)
21
+ assert_equal(TEST_ENTRY, @dictionary.random)
13
22
  @web_service.verify
14
23
  end
15
24
 
16
- def test_dictionary_calls_define
17
- @dictionary.web_service = @web_service.expect(:query, load_file('impromptu.html'), [:define, 'impromptu'])
18
- assert_equal(TEST_PHRASE, @dictionary.search('impromptu'))
25
+ def test_dictionary_calls_search
26
+ @dictionary.web_service = @web_service.expect(:search, @response, ['impromptu'])
27
+ assert_equal(TEST_ENTRY, @dictionary.search('impromptu'))
28
+ @web_service.verify
29
+ end
30
+
31
+ def test_dictionary_returns_empty_for_missing_phrases
32
+ @response.stream = load_file('missing.html')
33
+ @dictionary.web_service = @web_service.expect(:search, @response, ['gubble'])
34
+ assert_equal(EMPTY_ENTRY, @dictionary.search('gubble'))
19
35
  @web_service.verify
20
36
  end
21
37
  end
@@ -3,19 +3,54 @@ require 'test_helper'
3
3
  class WebTest < MiniTest::Unit::TestCase
4
4
 
5
5
  def setup
6
- @web_service = (Urban::Web.new).extend Stub
7
- @web_service.stub(:open) { |arg| return arg; }
6
+ @web_module = (Object.new).extend(Urban::Web).extend(Stub)
8
7
  end
9
8
 
10
- def test_web_sends_request_to_random
11
- expected = 'http://www.urbandictionary.com/random.php'
12
- actual = @web_service.query(:random)
13
- assert_equal(expected, actual)
9
+ class WebFetchTest < WebTest
10
+ def setup
11
+ super
12
+ @web_module.stub(:open) { |arg| arg }
13
+ end
14
+
15
+ def test_fetch_with_no_params
16
+ expected = 'http://www.urbandictionary.com/test.php'
17
+ actual = @web_module.fetch('test.php')
18
+ assert_equal(expected, actual)
19
+ end
20
+
21
+ def test_fetch_with_params
22
+ expected = /http:\/\/www\.urbandictionary\.com\/test\.php\?\w+=\w+&\w+=\w+/
23
+ actual = @web_module.fetch('test.php', :name => 'foo', :term => 'bar')
24
+ assert_match(expected, actual)
25
+ end
14
26
  end
15
27
 
16
- def test_web_sends_request_to_define_with_phrase
17
- expected = 'http://www.urbandictionary.com/define.php?term=Cookie%20monster'
18
- actual = @web_service.query(:define, 'Cookie monster')
19
- assert_equal(expected, actual)
28
+ class WebInterfaceTest < WebTest
29
+
30
+ def setup
31
+ super
32
+ @expected = OpenStruct.new
33
+ @expected.base_uri = 'http://www.urbandictionary.com/define.php?term=impromptu'
34
+
35
+ @web_module.stub(:open) do |arg|
36
+ result = OpenStruct.new
37
+ result.base_uri = 'http://www.urbandictionary.com/define.php?term=impromptu'
38
+ result
39
+ end
40
+ end
41
+
42
+ def test_returns_response_for_random_word
43
+ actual = @web_module.random
44
+
45
+ assert_equal(@expected.base_uri, actual.url)
46
+ assert_equal(@expected, actual.stream)
47
+ end
48
+
49
+ def test_returns_response_for_define_with_phrase
50
+ actual = @web_module.search('cookie monster')
51
+
52
+ assert_equal(@expected.base_uri, actual.url)
53
+ assert_equal(@expected, actual.stream)
54
+ end
20
55
  end
21
56
  end