codeless_code 0.1.7 → 0.1.8

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 (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