codeless_code 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +1 -1
  3. data/.reek.yml +14 -0
  4. data/.rubocop.yml +18 -0
  5. data/.ruby-version +1 -0
  6. data/{test/test_codeless_code.rb → .travis.yml} +12 -10
  7. data/Gemfile +5 -0
  8. data/Gemfile.lock +21 -0
  9. data/Guardfile +13 -1
  10. data/README.md +6 -0
  11. data/Rakefile +26 -11
  12. data/VERSION +1 -1
  13. data/bin/codeless_code +3 -1
  14. data/codeless_code.gemspec +33 -12
  15. data/lib/codeless_code/catalog.rb +3 -1
  16. data/lib/codeless_code/cli.rb +56 -24
  17. data/lib/codeless_code/commands/filter_fables.rb +15 -10
  18. data/lib/codeless_code/commands/list_translations.rb +3 -0
  19. data/lib/codeless_code/fable.rb +42 -53
  20. data/lib/codeless_code/fable_set.rb +8 -6
  21. data/lib/codeless_code/filters/builders.rb +4 -2
  22. data/lib/codeless_code/filters/composite.rb +3 -1
  23. data/lib/codeless_code/filters/date.rb +40 -30
  24. data/lib/codeless_code/filters/from_options.rb +45 -28
  25. data/lib/codeless_code/filters/headers/base.rb +61 -0
  26. data/lib/codeless_code/filters/{header_integer.rb → headers/integer.rb} +16 -19
  27. data/lib/codeless_code/filters/{header_string.rb → headers/string.rb} +12 -22
  28. data/lib/codeless_code/filters/lang.rb +3 -0
  29. data/lib/codeless_code/filters/translator.rb +7 -2
  30. data/lib/codeless_code/filters.rb +16 -8
  31. data/lib/codeless_code/formats/base.rb +20 -7
  32. data/lib/codeless_code/formats/parsers/base.rb +106 -0
  33. data/lib/codeless_code/formats/parsers/plain.rb +49 -0
  34. data/lib/codeless_code/formats/parsers/term.rb +79 -0
  35. data/lib/codeless_code/formats/plain.rb +21 -12
  36. data/lib/codeless_code/formats/raw.rb +2 -0
  37. data/lib/codeless_code/formats/term.rb +21 -15
  38. data/lib/codeless_code/language_set.rb +7 -4
  39. data/lib/codeless_code/options.rb +5 -3
  40. data/lib/codeless_code/renderers/fable.rb +13 -8
  41. data/lib/codeless_code/renderers/term_page.rb +46 -31
  42. data/lib/codeless_code.rb +119 -106
  43. data/test/codeless_code/commands/test_filter_fables.rb +89 -0
  44. data/test/codeless_code/filters/headers/test_integer.rb +86 -0
  45. data/test/codeless_code/filters/headers/test_string.rb +86 -0
  46. data/test/codeless_code/filters/test_builders.rb +4 -2
  47. data/test/codeless_code/filters/test_composite.rb +70 -0
  48. data/test/codeless_code/filters/test_date.rb +99 -0
  49. data/test/codeless_code/filters/test_langs.rb +50 -0
  50. data/test/codeless_code/filters/test_translator.rb +51 -0
  51. data/test/codeless_code/renderers/test_fable.rb +98 -0
  52. data/test/codeless_code/renderers/test_term_page.rb +87 -0
  53. data/test/codeless_code/test_catalog.rb +12 -5
  54. data/test/codeless_code/test_cli.rb +85 -0
  55. data/test/codeless_code/test_fable.rb +19 -10
  56. data/test/codeless_code/test_fable_set.rb +17 -5
  57. data/test/codeless_code/test_language_set.rb +16 -3
  58. data/test/codeless_code/test_options.rb +3 -11
  59. data/test/helper.rb +36 -10
  60. data/test/support/fs.rb +103 -0
  61. metadata +65 -11
  62. data/.document +0 -5
  63. data/data/README.md +0 -34
  64. data/lib/codeless_code/formats/plain_generator.rb +0 -157
  65. data/lib/codeless_code/formats/term_generator.rb +0 -167
  66. data/test/codeless_code/filters/test_header_integer.rb +0 -82
  67. data/test/codeless_code/filters/test_header_string.rb +0 -82
data/lib/codeless_code.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # codeless_code filters and prints fables from http://thecodelesscode.com
2
4
  # Copyright (C) 2018 Jon Sangster
3
5
  #
@@ -15,6 +17,7 @@
15
17
  # this program. If not, see <https://www.gnu.org/licenses/>.
16
18
  require 'pathname'
17
19
 
20
+ # +CodelessCode+ filters and renders {Fable fables}.
18
21
  module CodelessCode
19
22
  autoload :Catalog, 'codeless_code/catalog'
20
23
  autoload :Cli, 'codeless_code/cli'
@@ -24,20 +27,28 @@ module CodelessCode
24
27
  autoload :LanguageSet, 'codeless_code/language_set'
25
28
  autoload :Options, 'codeless_code/options'
26
29
 
30
+ # The "main" methods this applications supports
27
31
  module Commands
28
32
  autoload :FilterFables, 'codeless_code/commands/filter_fables'
29
33
  autoload :ListTranslations, 'codeless_code/commands/list_translations'
30
34
  end
31
35
 
36
+ # The methods in which {Fable fables} may be rendered as text.
32
37
  module Formats
33
38
  autoload :Base, 'codeless_code/formats/base'
34
39
  autoload :Plain, 'codeless_code/formats/plain'
35
- autoload :PlainGenerator, 'codeless_code/formats/plain_generator'
36
40
  autoload :Raw, 'codeless_code/formats/raw'
37
41
  autoload :Term, 'codeless_code/formats/term'
38
- autoload :TermGenerator, 'codeless_code/formats/term_generator'
42
+
43
+ # Custom parsers for the syntax tree generated by the +MediaCloth+ gem.
44
+ module Parsers
45
+ autoload :Base, 'codeless_code/formats/parsers/base'
46
+ autoload :Plain, 'codeless_code/formats/parsers/plain'
47
+ autoload :Term, 'codeless_code/formats/parsers/term'
48
+ end
39
49
  end
40
50
 
51
+ # The methods in which a {Fable fables's} body may be rendered as text.
41
52
  module Renderers
42
53
  autoload :Fable, 'codeless_code/renderers/fable'
43
54
  autoload :TermPage, 'codeless_code/renderers/term_page'
@@ -45,7 +56,7 @@ module CodelessCode
45
56
 
46
57
  VERSION = Pathname.new(__dir__).join('..', 'VERSION').read.strip.freeze
47
58
  DEFAULT_DATA = Pathname.new(__dir__)
48
- .join('..', 'data', 'the-codeless-code').freeze
59
+ .join('..', 'data', 'the-codeless-code').freeze
49
60
 
50
61
  BANNERS = [
51
62
  '%<cmd>s [INFO]',
@@ -53,108 +64,110 @@ module CodelessCode
53
64
  '%<cmd>s [OPTION]... [FILTER]... [NUMBER]'
54
65
  ].freeze
55
66
 
56
- OPTIONS = proc do |cmd, o|
57
- banner = [[BANNERS[0]] + BANNERS[1..-1].map { |s| "\n #{s}" }].join
58
-
59
- o.banner = format("Usage: #{banner}", cmd: cmd)
60
- o.separator ''
61
- o.separator 'Print or filter Codeless Code fables.'
62
-
63
- o.separator ''
64
- o.separator 'Info'
65
- o.boolean '-h', '--help'
66
- o.boolean '--list-translations'
67
- o.boolean '--version'
68
-
69
- o.separator ''
70
- o.separator 'Options'
71
- o.boolean '-c', '--columns', 'when listing fables, format the output ' \
72
- 'into columns'
73
- o.array '-e', '--headers', 'headers to include in the list output. ' \
74
- 'may be repeated'
75
- o.string '-f', '--format', 'one of: raw, plain, or term (default)'
76
- o.string '-o', '--output', 'write to the given file. "-" for STDOUT'
77
- o.string '-p', '--path', 'path to directory of fables. ' \
78
- 'see github.com/aldesantis/the-codeless-code'
79
- o.boolean '--random', 'select one fable, randomly, from the filtered list'
80
- o.string '--random-set', 'select n fables, randomly, from the filtered list'
81
- o.boolean '--daily', 'select one fable, randomly, from the filtered list' \
82
- 'based on today\'s date'
83
- o.boolean '--trace', 'print full error message if a fable fails to parse'
84
-
85
- o.string '-s', '--sort', 'when listing fables, sort by the given header'
86
- o.boolean '-r', '--reverse', 'when listing fables, reverse the order'
87
-
88
- o.separator ''
89
- o.separator 'Series Filters'
90
- o.string '-S', '--series'
91
- o.string '-Ss', '--series-start', 'series starts with'
92
- o.string '-Se', '--series-end', 'series ends with'
93
- o.boolean '-hS', '--has-series', 'has series listed'
94
- o.boolean '-nS', '--no-series', 'no series listed'
95
-
96
- o.separator ''
97
- o.separator 'Title Filters'
98
- o.string '-T', '--title'
99
- o.string '-Ts', '--title-start', 'title starts with'
100
- o.string '-Te', '--title-end', 'title ends with'
101
- o.boolean '-hT', '--has-title', 'has title listed'
102
- o.boolean '-nT', '--no-title', 'no title listed'
103
-
104
- o.separator ''
105
- o.separator 'Number Filters'
106
- o.string '-N', '--number', 'number (this is the default argument)'
107
- o.string '-Ng', '--number-gte', 'number or greater'
108
- o.string '-Nl', '--number-lte', 'number or lower'
109
- o.boolean '-hN', '--has-number', 'has number listed'
110
- o.boolean '-nN', '--no-number', 'no number listed'
111
-
112
- o.separator ''
113
- o.separator 'Language Filters'
114
- o.string '-L', '--lang', 'language code (default: en)'
115
-
116
- o.separator ''
117
- o.separator 'Translator Filters'
118
- o.string '-R', '--translator', 'translator\'s name (default: first ' \
119
- 'one, alphabetically)'
120
- o.string '-Rx', '--translator-exact', 'translator\'s name, ' \
121
- 'case-sensitive (default: first one, alphabetically)'
122
-
123
- o.separator ''
124
- o.separator 'Date Filters'
125
- o.string '-D', '--date', 'publish date'
126
- o.string '-Da', '--date-after', 'publish date or after'
127
- o.string '-Db', '--date-before', 'publish date or before'
128
- o.boolean '-nD', '--no-date', 'no publish date listed'
129
-
130
- o.separator ''
131
- o.separator 'Geekiness Filters'
132
- o.string '-G', '--geekiness', 'geekiness rating'
133
- o.string '-Gg', '--geekiness-gte', 'geekiness rating or greater'
134
- o.string '-Gl', '--geekiness-lte', 'geekiness rating or lower'
135
- o.boolean '-nG', '--no-geekiness', 'no geekiness rating'
136
-
137
- o.separator ''
138
- o.separator 'Name Filters'
139
- o.string '-A', '--name'
140
- o.string '-As', '--name-start', 'name starts with'
141
- o.string '-Ae', '--name-end', 'name ends with'
142
- o.boolean '-nA', '--no-name', 'no name listed'
143
-
144
- o.separator ''
145
- o.separator 'Credits Filters'
146
- o.string '-C', '--credits'
147
- o.string '-Cs', '--credits-start', 'credits starts with'
148
- o.string '-Ce', '--credits-end', 'credits ends with'
149
- o.boolean '-hC', '--has-credits', 'has credits listed'
150
- o.boolean '-nC', '--no-credits', 'no credits listed'
151
-
152
- o.separator ''
153
- o.separator 'Tagline Filters'
154
- o.string '-I', '--tagline'
155
- o.string '-Is', '--tagline-start', 'tagline starts with'
156
- o.string '-Ie', '--tagline-end', 'tagline ends with'
157
- o.boolean '-hI', '--has-tagline', 'has tagline listed'
158
- o.boolean '-nI', '--no-tagline', 'no tagline listed'
67
+ OPTIONS = proc do |cmd, opt|
68
+ banner =
69
+ [[BANNERS[0]] + BANNERS[1..-1].map { |str| "\n #{str}" }].join
70
+
71
+ opt.banner = format("Usage: #{banner}", cmd: cmd)
72
+ opt.separator ''
73
+ opt.separator 'Print or filter Codeless Code fables.'
74
+
75
+ opt.separator ''
76
+ opt.separator 'Info'
77
+ opt.boolean '-h', '--help'
78
+ opt.boolean '--list-translations'
79
+ opt.boolean '--version'
80
+
81
+ opt.separator ''
82
+ opt.separator 'Options'
83
+ opt.boolean '-c', '--columns', 'when listing fables, format the output ' \
84
+ 'into columns'
85
+ opt.array '-e', '--headers', 'headers to include in the list output. ' \
86
+ 'may be repeated'
87
+ opt.string '-f', '--format', 'one of: raw, plain, or term (default)'
88
+ opt.string '-o', '--output', 'write to the given file. "-" for STDOUT'
89
+ opt.string '-p', '--path', 'path to directory of fables. ' \
90
+ 'see github.com/aldesantis/the-codeless-code'
91
+ opt.boolean '--random', 'select one random fable from the filtered list'
92
+ opt.string '--random-set', 'select n random fables from the filtered list'
93
+ opt.boolean '--daily', 'select one fable, randomly, from the filtered ' \
94
+ 'list based on today\'s date'
95
+ opt.boolean '--trace', 'print full error message if a fable fails to parse'
96
+
97
+ opt.string '-s', '--sort', 'when listing fables, sort by the given header'
98
+ opt.boolean '-r', '--reverse', 'when listing fables, reverse the order'
99
+
100
+ opt.separator ''
101
+ opt.separator 'Series Filters'
102
+ opt.string '-S', '--series'
103
+ opt.string '-Ss', '--series-start', 'series starts with'
104
+ opt.string '-Se', '--series-end', 'series ends with'
105
+ opt.boolean '-hS', '--has-series', 'has series listed'
106
+ opt.boolean '-nS', '--no-series', 'no series listed'
107
+
108
+ opt.separator ''
109
+ opt.separator 'Title Filters'
110
+ opt.string '-T', '--title'
111
+ opt.string '-Ts', '--title-start', 'title starts with'
112
+ opt.string '-Te', '--title-end', 'title ends with'
113
+ opt.boolean '-hT', '--has-title', 'has title listed'
114
+ opt.boolean '-nT', '--no-title', 'no title listed'
115
+
116
+ opt.separator ''
117
+ opt.separator 'Number Filters'
118
+ opt.string '-N', '--number', 'number (this is the default argument)'
119
+ opt.string '-Ng', '--number-gte', 'number or greater'
120
+ opt.string '-Nl', '--number-lte', 'number or lower'
121
+ opt.boolean '-hN', '--has-number', 'has number listed'
122
+ opt.boolean '-nN', '--no-number', 'no number listed'
123
+
124
+ opt.separator ''
125
+ opt.separator 'Language Filters'
126
+ opt.string '-L', '--lang', 'language code (default: en)'
127
+
128
+ opt.separator ''
129
+ opt.separator 'Translator Filters'
130
+ opt.string '-R', '--translator', 'translator\'s name (default: first ' \
131
+ 'one, alphabetically)'
132
+ opt.string '-Rx', '--translator-exact',
133
+ 'translator\'s name, case-sensitive (default: first one, ' \
134
+ 'alphabetically)'
135
+
136
+ opt.separator ''
137
+ opt.separator 'Date Filters'
138
+ opt.string '-D', '--date', 'publish date'
139
+ opt.string '-Da', '--date-after', 'publish date or after'
140
+ opt.string '-Db', '--date-before', 'publish date or before'
141
+ opt.boolean '-nD', '--no-date', 'no publish date listed'
142
+
143
+ opt.separator ''
144
+ opt.separator 'Geekiness Filters'
145
+ opt.string '-G', '--geekiness', 'geekiness rating'
146
+ opt.string '-Gg', '--geekiness-gte', 'geekiness rating or greater'
147
+ opt.string '-Gl', '--geekiness-lte', 'geekiness rating or lower'
148
+ opt.boolean '-nG', '--no-geekiness', 'no geekiness rating'
149
+
150
+ opt.separator ''
151
+ opt.separator 'Name Filters'
152
+ opt.string '-A', '--name'
153
+ opt.string '-As', '--name-start', 'name starts with'
154
+ opt.string '-Ae', '--name-end', 'name ends with'
155
+ opt.boolean '-nA', '--no-name', 'no name listed'
156
+
157
+ opt.separator ''
158
+ opt.separator 'Credits Filters'
159
+ opt.string '-C', '--credits'
160
+ opt.string '-Cs', '--credits-start', 'credits starts with'
161
+ opt.string '-Ce', '--credits-end', 'credits ends with'
162
+ opt.boolean '-hC', '--has-credits', 'has credits listed'
163
+ opt.boolean '-nC', '--no-credits', 'no credits listed'
164
+
165
+ opt.separator ''
166
+ opt.separator 'Tagline Filters'
167
+ opt.string '-I', '--tagline'
168
+ opt.string '-Is', '--tagline-start', 'tagline starts with'
169
+ opt.string '-Ie', '--tagline-end', 'tagline ends with'
170
+ opt.boolean '-hI', '--has-tagline', 'has tagline listed'
171
+ opt.boolean '-nI', '--no-tagline', 'no tagline listed'
159
172
  end
160
173
  end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ # codeless_code filters and prints fables from http://thecodelesscode.com
4
+ # Copyright (C) 2018 Jon Sangster
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify it under
7
+ # the terms of the GNU General Public License as published by the Free Software
8
+ # Foundation, either version 3 of the License, or (at your option) any later
9
+ # version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
+ # details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License along with
17
+ # this program. If not, see <https://www.gnu.org/licenses/>.
18
+ require 'helper'
19
+ require 'minitest/mock'
20
+
21
+ module Commands
22
+ class TestFilterFables < UnitTest
23
+ def setup
24
+ @pager = ENV.delete('PAGER')
25
+ end
26
+
27
+ def teardown
28
+ ENV['PAGER'] = @pager
29
+ end
30
+
31
+ def test_call_default
32
+ expected = ['00123 Test Case', '00234 Test Case 2', ''].join("\n")
33
+ assert_output(expected) { command.call }
34
+ end
35
+
36
+ def test_call_single_by_number
37
+ [
38
+ " Test Case\n" \
39
+ "==================\n" \
40
+ "Number: 123\n" \
41
+ " Date: 2018-12-23\n" \
42
+ "------------------\n" \
43
+ "\n" \
44
+ "body\n"
45
+ ].each { |expected| assert_output(expected) { command('123').call } }
46
+ end
47
+
48
+ def test_call_match_none
49
+ assert_output(nil, "None found.\n") { command('9999').call }
50
+ end
51
+
52
+ def test_call_reverse
53
+ expected = ['00234 Test Case 2', '00123 Test Case', ''].join("\n")
54
+ assert_output(expected) { command('-r').call }
55
+ end
56
+
57
+ def test_call_sort
58
+ expected = ['00234 Test Case 2', '00123 Test Case', ''].join("\n")
59
+ assert_output(expected) { command('-s', 'Date').call }
60
+ end
61
+
62
+ private
63
+
64
+ def command(*args)
65
+ opts = options(*args)
66
+ opts.instance_variable_set(:@data_dir, fake_fs)
67
+ Commands::FilterFables.new(catalog, opts)
68
+ end
69
+
70
+ def fake_fs # rubocop:disable Metrics/MethodLength
71
+ FakeDir.new('/').tap do |fs|
72
+ fs.create_path('en-test/case-123.txt', <<-FABLE)
73
+ Title: Test Case
74
+ Number: 123
75
+ Date: 2018-12-23
76
+
77
+ body
78
+ FABLE
79
+ fs.create_path('en-test/case-234.txt', <<-FABLE)
80
+ Title: Test Case 2
81
+ Number: 234
82
+ Date: 2000-12-23
83
+
84
+ body 2
85
+ FABLE
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ # codeless_code filters and prints fables from http://thecodelesscode.com
4
+ # Copyright (C) 2018 Jon Sangster
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify it under
7
+ # the terms of the GNU General Public License as published by the Free Software
8
+ # Foundation, either version 3 of the License, or (at your option) any later
9
+ # version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
+ # details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License along with
17
+ # this program. If not, see <https://www.gnu.org/licenses/>.
18
+ require 'helper'
19
+
20
+ module Filters
21
+ module Headers
22
+ class TestInteger < UnitTest
23
+ def test_enabled?
24
+ refute_predicate filter('Test'), :enabled?
25
+ refute_predicate filter('Test', exclude: false), :enabled?
26
+
27
+ assert_predicate filter('Test', exact: 1), :enabled?
28
+ assert_predicate filter('Test', min: 1), :enabled?
29
+ assert_predicate filter('Test', max: 1), :enabled?
30
+ assert_predicate filter('Test', exclude: true), :enabled?
31
+ end
32
+
33
+ def test_call_exact
34
+ assert_filter(exact: 100)
35
+
36
+ refute_filter(exact: 123)
37
+ end
38
+
39
+ def test_call_min
40
+ assert_filter(min: 99)
41
+ assert_filter(min: 100)
42
+
43
+ refute_filter(min: 101)
44
+ end
45
+
46
+ def test_call_max
47
+ assert_filter(max: 100)
48
+ assert_filter(max: 101)
49
+
50
+ refute_filter(max: 99)
51
+ end
52
+
53
+ def test_call_exclude
54
+ assert_filter('MissingHeader', exclude: true)
55
+
56
+ refute_filter(exclude: true)
57
+ end
58
+
59
+ private
60
+
61
+ def filter(key, **opts)
62
+ Filters::Headers::Integer.new(key, **opts)
63
+ end
64
+
65
+ def assert_filter(key = 'Test', **opts)
66
+ fab = create_fable
67
+ filt = filter(key, **opts)
68
+ assert filt.call(fab), format('Expected %p to match %p', opts, fab)
69
+ end
70
+
71
+ def refute_filter(key = 'Test', **opts)
72
+ fab = create_fable
73
+ filt = filter(key, **opts)
74
+ refute filt.call(fab), format('Expected %p not to match %p', opts, fab)
75
+ end
76
+
77
+ def create_fable
78
+ mock_fable(<<-BODY.strip)
79
+ Test: 100
80
+
81
+ body
82
+ BODY
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ # codeless_code filters and prints fables from http://thecodelesscode.com
4
+ # Copyright (C) 2018 Jon Sangster
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify it under
7
+ # the terms of the GNU General Public License as published by the Free Software
8
+ # Foundation, either version 3 of the License, or (at your option) any later
9
+ # version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
+ # details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License along with
17
+ # this program. If not, see <https://www.gnu.org/licenses/>.
18
+ require 'helper'
19
+
20
+ module Filters
21
+ module Headers
22
+ class TestString < UnitTest
23
+ def test_enabled?
24
+ refute_predicate filter('Test'), :enabled?
25
+ refute_predicate filter('Test', exclude: false), :enabled?
26
+
27
+ assert_predicate filter('Test', exact: 'foo'), :enabled?
28
+ assert_predicate filter('Test', start_with: 'foo'), :enabled?
29
+ assert_predicate filter('Test', end_with: 'foo'), :enabled?
30
+ assert_predicate filter('Test', exclude: true), :enabled?
31
+ end
32
+
33
+ def test_call_exact
34
+ assert_filter(exact: 'some text')
35
+
36
+ refute_filter(exact: 'something else')
37
+ end
38
+
39
+ def test_call_start_with
40
+ assert_filter(start_with: 'some')
41
+ assert_filter(start_with: '')
42
+
43
+ refute_filter(start_with: 'something else')
44
+ end
45
+
46
+ def test_call_end_with
47
+ assert_filter(end_with: 'text')
48
+ assert_filter(end_with: '')
49
+
50
+ refute_filter(end_with: 'something else')
51
+ end
52
+
53
+ def test_call_exclude
54
+ assert_filter('MissingHeader', exclude: true)
55
+
56
+ refute_filter(exclude: true)
57
+ end
58
+
59
+ private
60
+
61
+ def filter(key, **opts)
62
+ Filters::Headers::String.new(key, **opts)
63
+ end
64
+
65
+ def assert_filter(key = 'Test', **opts)
66
+ fab = create_fable
67
+ filt = filter(key, **opts)
68
+ assert filt.call(fab), format('Expected %p to match %p', opts, fab)
69
+ end
70
+
71
+ def refute_filter(key = 'Test', **opts)
72
+ fab = create_fable
73
+ filt = filter(key, **opts)
74
+ refute filt.call(fab), format('Expected %p not to match %p', opts, fab)
75
+ end
76
+
77
+ def create_fable
78
+ mock_fable(<<-BODY.strip)
79
+ Test: some text
80
+
81
+ body
82
+ BODY
83
+ end
84
+ end
85
+ end
86
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # codeless_code filters and prints fables from http://thecodelesscode.com
2
4
  # Copyright (C) 2018 Jon Sangster
3
5
  #
@@ -19,13 +21,13 @@ module Filters
19
21
  class TestBuilders < UnitTest
20
22
  def test_header_integer_filter
21
23
  assert_kind_of Class, Filters::Builders.header_integer_filter('FooOne')
22
- assert_kind_of Filters::HeaderInteger,
24
+ assert_kind_of Filters::Headers::Integer,
23
25
  Filters::Builders.header_integer_filter('FooTwo').new
24
26
  end
25
27
 
26
28
  def test_header_string_filter
27
29
  assert_kind_of Class, Filters::Builders.header_string_filter('BarOne')
28
- assert_kind_of Filters::HeaderString,
30
+ assert_kind_of Filters::Headers::String,
29
31
  Filters::Builders.header_string_filter('BarTwo').new
30
32
  end
31
33
  end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ # codeless_code filters and prints fables from http://thecodelesscode.com
4
+ # Copyright (C) 2018 Jon Sangster
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify it under
7
+ # the terms of the GNU General Public License as published by the Free Software
8
+ # Foundation, either version 3 of the License, or (at your option) any later
9
+ # version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
+ # details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License along with
17
+ # this program. If not, see <https://www.gnu.org/licenses/>.
18
+ require 'helper'
19
+
20
+ module Filters
21
+ class TestComposite < UnitTest
22
+ def test_enabled?
23
+ assert_predicate filter(matching_filter), :enabled?
24
+ assert_predicate filter(matchless_filter), :enabled?
25
+ assert_predicate filter(filter(matching_filter)), :enabled?
26
+ end
27
+
28
+ def test_not_enabled?
29
+ refute_predicate filter, :enabled?
30
+ refute_predicate filter(filter(filter)), :enabled?
31
+ end
32
+
33
+ def test_call_matching
34
+ assert filter(matching_filter).call(create_fable),
35
+ 'Expected composite filter to match'
36
+ end
37
+
38
+ def test_call_matchless
39
+ refute filter(matchless_filter).call(create_fable),
40
+ 'Expected composite filter to match'
41
+ end
42
+
43
+ def test_call_empty
44
+ refute filter.call(create_fable),
45
+ 'Expected an empty composite to match nothing'
46
+ end
47
+
48
+ private
49
+
50
+ def filter(*filters)
51
+ Filters::Composite.new(*filters)
52
+ end
53
+
54
+ def matching_filter
55
+ Filters::Number.new(exact: 123)
56
+ end
57
+
58
+ def matchless_filter
59
+ Filters::Date.new(exact: '2018')
60
+ end
61
+
62
+ def create_fable
63
+ mock_fable(<<-BODY.strip)
64
+ Number: 123
65
+
66
+ body
67
+ BODY
68
+ end
69
+ end
70
+ end