mime-types 2.99.3 → 3.2.2

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 (52) hide show
  1. checksums.yaml +5 -5
  2. data/{Code-of-Conduct.rdoc → Code-of-Conduct.md} +19 -20
  3. data/Contributing.md +139 -0
  4. data/History.md +208 -0
  5. data/{Licence.rdoc → Licence.md} +4 -18
  6. data/Manifest.txt +8 -25
  7. data/README.rdoc +63 -67
  8. data/Rakefile +144 -55
  9. data/lib/mime/type/columnar.rb +29 -62
  10. data/lib/mime/type.rb +192 -417
  11. data/lib/mime/types/_columnar.rb +137 -0
  12. data/lib/mime/types/cache.rb +51 -73
  13. data/lib/mime/types/columnar.rb +2 -147
  14. data/lib/mime/types/container.rb +94 -0
  15. data/lib/mime/types/deprecations.rb +5 -24
  16. data/lib/mime/types/full.rb +19 -0
  17. data/lib/mime/types/loader.rb +12 -141
  18. data/lib/mime/types/logger.rb +4 -0
  19. data/lib/mime/types/registry.rb +90 -0
  20. data/lib/mime/types.rb +43 -139
  21. data/lib/mime-types.rb +1 -1
  22. data/test/minitest_helper.rb +6 -12
  23. data/test/test_mime_type.rb +473 -455
  24. data/test/test_mime_types.rb +136 -86
  25. data/test/test_mime_types_cache.rb +83 -53
  26. data/test/test_mime_types_class.rb +119 -97
  27. data/test/test_mime_types_lazy.rb +27 -23
  28. data/test/test_mime_types_loader.rb +7 -32
  29. metadata +102 -62
  30. data/Contributing.rdoc +0 -170
  31. data/History-Types.rdoc +0 -454
  32. data/History.rdoc +0 -590
  33. data/data/mime-types.json +0 -1
  34. data/data/mime.content_type.column +0 -1980
  35. data/data/mime.docs.column +0 -1980
  36. data/data/mime.encoding.column +0 -1980
  37. data/data/mime.friendly.column +0 -1980
  38. data/data/mime.obsolete.column +0 -1980
  39. data/data/mime.registered.column +0 -1980
  40. data/data/mime.signature.column +0 -1980
  41. data/data/mime.use_instead.column +0 -1980
  42. data/data/mime.xrefs.column +0 -1980
  43. data/docs/COPYING.txt +0 -339
  44. data/docs/artistic.txt +0 -127
  45. data/lib/mime/types/loader_path.rb +0 -15
  46. data/support/apache_mime_types.rb +0 -108
  47. data/support/benchmarks/load.rb +0 -64
  48. data/support/benchmarks/load_allocations.rb +0 -83
  49. data/support/benchmarks/object_counts.rb +0 -41
  50. data/support/convert/columnar.rb +0 -88
  51. data/support/convert.rb +0 -158
  52. data/support/iana_registry.rb +0 -172
@@ -1,15 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # -*- ruby encoding: utf-8 -*-
2
4
 
3
5
  require 'mime/types'
4
6
  require 'minitest_helper'
5
7
 
6
- class TestMIMEType < Minitest::Test
7
- def make(content_type)
8
+ describe MIME::Type do
9
+ # it { fail }
10
+
11
+ def mime_type(content_type)
8
12
  MIME::Type.new(content_type) { |mt| yield mt if block_given? }
9
13
  end
10
14
 
11
- def make_javascript
12
- make('application/javascript') do |js|
15
+ let(:x_appl_x_zip) {
16
+ mime_type('x-appl/x-zip') { |t| t.extensions = %w(zip zp) }
17
+ }
18
+ let(:text_plain) { mime_type('text/plain') }
19
+ let(:text_html) { mime_type('text/html') }
20
+ let(:image_jpeg) { mime_type('image/jpeg') }
21
+ let(:application_javascript) {
22
+ mime_type('application/javascript') do |js|
13
23
  js.friendly('en' => 'JavaScript')
14
24
  js.xrefs = {
15
25
  'rfc' => %w(rfc4239 rfc4239),
@@ -17,580 +27,588 @@ class TestMIMEType < Minitest::Test
17
27
  }
18
28
  js.encoding = '8bit'
19
29
  js.extensions = %w(js sj)
20
- assert_deprecated('MIME::Type#references=') do
21
- js.references = :anything
22
- end
23
30
  js.registered = true
24
-
25
- yield js if block_given?
26
31
  end
27
- end
28
-
29
- def make_yaml_mime_type
30
- make('text/x-yaml') do |yaml|
32
+ }
33
+ let(:text_x_yaml) {
34
+ mime_type('text/x-yaml') do |yaml|
31
35
  yaml.extensions = %w(yaml yml)
32
36
  yaml.encoding = '8bit'
33
- assert_deprecated('MIME::Type#system=') do
34
- yaml.system = 'd9d172f608'
35
- end
36
37
  yaml.friendly('en' => 'YAML Structured Document')
37
38
  end
38
- end
39
+ }
40
+ let(:text_x_yaml_with_docs) {
41
+ text_x_yaml.dup.tap do |yaml|
42
+ yaml.docs = 'Test YAML'
43
+ end
44
+ }
39
45
 
40
- def make_yaml_mime_type_with_docs
41
- make('text/x-yaml') do |yaml|
42
- yaml.extensions = %w(yaml yml)
43
- yaml.encoding = '8bit'
44
- assert_deprecated('MIME::Type#system=') do
45
- yaml.system = 'd9d172f608'
46
- end
47
- yaml.docs = 'Test YAML'
46
+ describe '.simplified' do
47
+ it 'leaves normal types alone' do
48
+ assert_equal 'text/plain', MIME::Type.simplified('text/plain')
49
+ end
50
+
51
+ it 'does not remove x- prefixes by default' do
52
+ assert_equal 'application/x-msword',
53
+ MIME::Type.simplified('application/x-msword')
54
+ assert_equal 'x-xyz/abc', MIME::Type.simplified('x-xyz/abc')
55
+ end
56
+
57
+ it 'removes x- prefixes when requested' do
58
+ assert_equal 'application/msword',
59
+ MIME::Type.simplified('application/x-msword', remove_x_prefix: true)
60
+ assert_equal 'xyz/abc',
61
+ MIME::Type.simplified('x-xyz/abc', remove_x_prefix: true)
62
+ end
63
+
64
+ it 'lowercases mixed-case types' do
65
+ assert_equal 'text/vcard', MIME::Type.simplified('text/vCard')
66
+ end
67
+
68
+ it 'returns nil when the value provided is not a valid content type' do
69
+ assert_nil MIME::Type.simplified('text')
48
70
  end
49
71
  end
50
72
 
51
- def setup
52
- @applzip = MIME::Type.new('x-appl/x-zip') { |t|
53
- t.extensions = %w(zip zp)
54
- }
73
+ describe '.i18n_key' do
74
+ it 'converts text/plain to text.plain' do
75
+ assert_equal 'text.plain', MIME::Type.i18n_key('text/plain')
76
+ end
77
+
78
+ it 'does not remove x-prefixes' do
79
+ assert_equal 'application.x-msword',
80
+ MIME::Type.i18n_key('application/x-msword')
81
+ end
82
+
83
+ it 'converts text/vCard to text.vcard' do
84
+ assert_equal 'text.vcard', MIME::Type.i18n_key('text/vCard')
85
+ end
86
+
87
+ it 'returns nil when the value provided is not a valid content type' do
88
+ assert_nil MIME::Type.i18n_key('text')
89
+ end
55
90
  end
56
91
 
57
- def test_class_from_array
58
- yaml = nil
59
- assert_deprecated('MIME::Type.from_array') do
60
- yaml = MIME::Type.from_array(
61
- 'text/x-yaml',
62
- %w(yaml yml),
63
- '8bit',
64
- 'd9d172f608'
92
+ describe '.new' do
93
+ it 'fails if an invalid content type is provided' do
94
+ exception = assert_raises MIME::Type::InvalidContentType do
95
+ MIME::Type.new('apps')
96
+ end
97
+ assert_equal 'Invalid Content-Type "apps"', exception.to_s
98
+ end
99
+
100
+ it 'creates a valid content type just from a string' do
101
+ type = MIME::Type.new('text/x-yaml')
102
+
103
+ assert_instance_of MIME::Type, type
104
+ assert_equal 'text/x-yaml', type.content_type
105
+ end
106
+
107
+ it 'yields the content type in a block' do
108
+ MIME::Type.new('text/x-yaml') do |type|
109
+ assert_instance_of MIME::Type, type
110
+ assert_equal 'text/x-yaml', type.content_type
111
+ end
112
+ end
113
+
114
+ it 'creates a valid content type from a hash' do
115
+ type = MIME::Type.new(
116
+ 'content-type' => 'text/x-yaml',
117
+ 'obsolete' => true
65
118
  )
119
+ assert_instance_of MIME::Type, type
120
+ assert_equal 'text/x-yaml', type.content_type
121
+ assert type.obsolete?
66
122
  end
67
- assert_instance_of(MIME::Type, yaml)
68
- assert_equal('text/yaml', yaml.simplified)
69
- assert_deprecated('MIME::Type.from_array') do
70
- assert_raises(ArgumentError) { MIME::Type.from_array }
123
+
124
+ it 'creates a valid content type from an array' do
125
+ type = MIME::Type.new(%w(text/x-yaml yaml yml yz))
126
+ assert_instance_of MIME::Type, type
127
+ assert_equal 'text/x-yaml', type.content_type
128
+ assert_equal %w(yaml yml yz), type.extensions
71
129
  end
72
130
  end
73
131
 
74
- def test_class_from_hash
75
- yaml = nil
76
- assert_deprecated('MIME::Type.from_hash') do
77
- yaml = MIME::Type.from_hash('Content-Type' => 'text/x-yaml',
78
- 'Content-Transfer-Encoding' => '8bit',
79
- 'System' => 'd9d172f608',
80
- 'Extensions' => %w(yaml yml))
132
+ describe '#like?' do
133
+ it 'compares two MIME::Types on #simplified values without x- prefixes' do
134
+ assert text_plain.like?(text_plain)
135
+ refute text_plain.like?(text_html)
81
136
  end
82
- assert_instance_of(MIME::Type, yaml)
83
- assert_equal('text/yaml', yaml.simplified)
84
- end
85
137
 
86
- def test_class_from_mime_type
87
- zip2 = nil
88
- assert_deprecated('MIME::Type.from_mime_type') do
89
- zip2 = MIME::Type.from_mime_type(@applzip)
138
+ it 'compares MIME::Type against string without x- prefixes' do
139
+ assert text_plain.like?(text_plain.to_s)
140
+ refute text_plain.like?(text_html.to_s)
90
141
  end
91
- assert_instance_of(MIME::Type, @applzip)
92
- assert_equal('appl/zip', @applzip.simplified)
93
- refute_equal(@applzip.object_id, zip2.object_id)
94
142
  end
95
143
 
96
- def test_class_simplified
97
- assert_equal('text/plain', MIME::Type.simplified('text/plain'))
98
- assert_equal('image/jpeg', MIME::Type.simplified('image/jpeg'))
99
- assert_equal('application/msword', MIME::Type.simplified('application/x-msword'))
100
- assert_equal('text/vcard', MIME::Type.simplified('text/vCard'))
101
- assert_equal('application/pkcs7-mime', MIME::Type.simplified('application/pkcs7-mime'))
102
- assert_equal('xyz/abc', MIME::Type.simplified('x-xyz/abc'))
103
- assert_nil(MIME::Type.simplified('text'))
104
- end
144
+ describe '#<=>' do
145
+ it 'correctly compares identical types' do
146
+ assert_equal text_plain, text_plain
147
+ end
105
148
 
106
- def test_class_i18n_key
107
- assert_equal('text.plain', MIME::Type.i18n_key('text/plain'))
108
- assert_equal('image.jpeg', MIME::Type.i18n_key('image/jpeg'))
109
- assert_equal('application.msword', MIME::Type.i18n_key('application/x-msword'))
110
- assert_equal('text.vcard', MIME::Type.i18n_key('text/vCard'))
111
- assert_equal('application.pkcs7-mime', MIME::Type.i18n_key('application/pkcs7-mime'))
112
- assert_equal('xyz.abc', MIME::Type.i18n_key('x-xyz/abc'))
113
- assert_nil(MIME::Type.i18n_key('text'))
114
- end
149
+ it 'correctly compares equivalent types' do
150
+ right = mime_type('text/Plain')
151
+ refute_same text_plain, right
152
+ assert_equal text_plain, right
153
+ end
115
154
 
116
- def test_spaceship_compare # '<=>'
117
- assert(MIME::Type.new('text/plain') == MIME::Type.new('text/plain')) # rubocop:disable Lint/UselessComparison
118
- assert(MIME::Type.new('text/plain') != MIME::Type.new('image/jpeg'))
119
- assert(MIME::Type.new('text/plain') == 'text/plain')
120
- assert(MIME::Type.new('text/plain') != 'image/jpeg')
121
- assert(MIME::Type.new('text/plain') > MIME::Type.new('text/html'))
122
- assert(MIME::Type.new('text/plain') > 'text/html')
123
- assert(MIME::Type.new('text/html') < MIME::Type.new('text/plain'))
124
- assert(MIME::Type.new('text/html') < 'text/plain')
125
- assert('text/html' == MIME::Type.new('text/html'))
126
- assert('text/html' < MIME::Type.new('text/plain'))
127
- assert('text/plain' > MIME::Type.new('text/html'))
128
- end
155
+ it 'correctly compares types that sort earlier' do
156
+ refute_equal text_html, text_plain
157
+ assert_operator text_html, :<, text_plain
158
+ end
129
159
 
130
- def test_ascii_eh
131
- assert(MIME::Type.new('text/plain').ascii?)
132
- refute(MIME::Type.new('image/jpeg').ascii?)
133
- refute(MIME::Type.new('application/x-msword').ascii?)
134
- assert(MIME::Type.new('text/vCard').ascii?)
135
- refute(MIME::Type.new('application/pkcs7-mime').ascii?)
136
- refute(@applzip.ascii?)
137
- end
160
+ it 'correctly compares types that sort later' do
161
+ refute_equal text_plain, text_html
162
+ assert_operator text_plain, :>, text_html
163
+ end
138
164
 
139
- def test_binary_eh
140
- refute(MIME::Type.new('text/plain').binary?)
141
- assert(MIME::Type.new('image/jpeg').binary?)
142
- assert(MIME::Type.new('application/x-msword').binary?)
143
- refute(MIME::Type.new('text/vCard').binary?)
144
- assert(MIME::Type.new('application/pkcs7-mime').binary?)
145
- assert(@applzip.binary?)
146
- end
165
+ it 'correctly compares types against equivalent strings' do
166
+ assert_equal text_plain, 'text/plain'
167
+ end
147
168
 
148
- def test_complete_eh
149
- yaml = make_yaml_mime_type
150
- assert(yaml.complete?)
151
- yaml.extensions = nil
152
- refute(yaml.complete?)
153
- end
169
+ it 'correctly compares types against strings that sort earlier' do
170
+ refute_equal text_html, 'text/plain'
171
+ assert_operator text_html, :<, 'text/plain'
172
+ end
154
173
 
155
- def test_content_type
156
- assert_equal('text/plain', MIME::Type.new('text/plain').content_type)
157
- assert_equal('image/jpeg', MIME::Type.new('image/jpeg').content_type)
158
- assert_equal('application/x-msword',
159
- MIME::Type.new('application/x-msword').content_type)
160
- assert_equal('text/vCard', MIME::Type.new('text/vCard').content_type)
161
- assert_equal('application/pkcs7-mime',
162
- MIME::Type.new('application/pkcs7-mime').content_type)
163
- assert_equal('x-appl/x-zip', @applzip.content_type)
164
- assert_equal('base64', @applzip.encoding)
165
- end
174
+ it 'correctly compares types against strings that sort later' do
175
+ refute_equal text_plain, 'text/html'
176
+ assert_operator text_plain, :>, 'text/html'
177
+ end
166
178
 
167
- def test_encoding
168
- assert_equal('quoted-printable', MIME::Type.new('text/plain').encoding)
169
- assert_equal('base64', MIME::Type.new('image/jpeg').encoding)
170
- assert_equal('base64', MIME::Type.new('application/x-msword').encoding)
171
- assert_equal('quoted-printable', MIME::Type.new('text/vCard').encoding)
172
- assert_equal('base64', MIME::Type.new('application/pkcs7-mime').encoding)
179
+ it 'correctly compares against nil' do
180
+ refute_equal text_html, nil
181
+ assert_operator text_plain, :<, nil
182
+ end
173
183
  end
174
184
 
175
- def test_encoding_equals
176
- yaml = make_yaml_mime_type
177
- assert_equal('8bit', yaml.encoding)
178
- yaml.encoding = 'base64'
179
- assert_equal('base64', yaml.encoding)
180
- yaml.encoding = :default
181
- assert_equal('quoted-printable', yaml.encoding)
182
- assert_raises(MIME::Type::InvalidEncoding) {
183
- yaml.encoding = 'binary'
184
- }
185
- end
185
+ describe '#ascii?' do
186
+ it 'defaults to true for text/* types' do
187
+ assert text_plain.ascii?
188
+ end
186
189
 
187
- def test_default_encoding
188
- %w(text/plain text/html).each { |mt|
189
- assert_equal('quoted-printable', MIME::Type.new(mt).default_encoding)
190
- }
191
- %w(image/jpeg applicatoin/pkcs7-mime).each { |mt|
192
- assert_equal('base64', MIME::Type.new(mt).default_encoding)
193
- }
190
+ it 'defaults to false for non-text/* types' do
191
+ refute image_jpeg.ascii?
192
+ end
194
193
  end
195
194
 
196
- def test_docs
197
- yaml = make_yaml_mime_type_with_docs
198
- assert_equal('Test YAML', yaml.docs)
199
- end
195
+ describe '#binary?' do
196
+ it 'defaults to false for text/* types' do
197
+ refute text_plain.binary?
198
+ end
200
199
 
201
- def test_docs_equals
202
- yaml = make_yaml_mime_type
203
- assert_equal [], yaml.docs
204
- yaml.docs = 'YAML docs'
205
- assert_equal('YAML docs', yaml.docs)
200
+ it 'defaults to true for non-text/* types' do
201
+ assert image_jpeg.binary?
202
+ end
206
203
  end
207
204
 
208
- def test_eql?
209
- assert(MIME::Type.new('text/plain').eql?(MIME::Type.new('text/plain')))
210
- refute(MIME::Type.new('text/plain').eql?(MIME::Type.new('image/jpeg')))
211
- refute(MIME::Type.new('text/plain').eql?('text/plain'))
212
- refute(MIME::Type.new('text/plain').eql?('image/jpeg'))
205
+ describe '#complete?' do
206
+ it 'is true when there are extensions' do
207
+ assert text_x_yaml.complete?
208
+ end
209
+
210
+ it 'is false when there are no extensions' do
211
+ refute mime_type('text/plain').complete?
212
+ end
213
213
  end
214
214
 
215
- def test_extensions
216
- yaml = make_yaml_mime_type
217
- assert_equal(%w(yaml yml), yaml.extensions)
218
- assert_equal(2, @applzip.extensions.size)
219
- assert_equal(%w(zip zp), @applzip.extensions)
215
+ describe '#content_type' do
216
+ it 'preserves the original case' do
217
+ assert_equal 'text/plain', text_plain.content_type
218
+ assert_equal 'text/vCard', mime_type('text/vCard').content_type
219
+ end
220
+
221
+ it 'does not remove x- prefixes' do
222
+ assert_equal 'x-appl/x-zip', x_appl_x_zip.content_type
223
+ end
220
224
  end
221
225
 
222
- def test_add_extensions
223
- expected = make_yaml_mime_type
224
- test_doc = make_yaml_mime_type
225
- test_doc.add_extensions(nil)
226
- assert_equal(expected.extensions, test_doc.extensions)
227
- test_doc.add_extensions('yaml')
228
- assert_equal(expected.extensions, test_doc.extensions)
229
- test_doc.add_extensions(%w(yaml))
230
- assert_equal(expected.extensions, test_doc.extensions)
231
- test_doc.add_extensions('yz')
232
- assert_equal(%w(yaml yml yz), test_doc.extensions)
226
+ describe '#default_encoding' do
227
+ it 'is quoted-printable for text/* types' do
228
+ assert_equal 'quoted-printable', text_plain.default_encoding
229
+ end
230
+
231
+ it 'is base64 for non-text/* types' do
232
+ assert_equal 'base64', image_jpeg.default_encoding
233
+ end
233
234
  end
234
235
 
235
- def test_extensions_equals
236
- yaml = make_yaml_mime_type
237
- yaml.extensions = 'yaml'
238
- assert_equal(%w(yaml), yaml.extensions)
236
+ describe '#encoding, #encoding=' do
237
+ it 'returns #default_encoding if not set explicitly' do
238
+ assert_equal 'quoted-printable', text_plain.encoding
239
+ assert_equal 'base64', image_jpeg.encoding
240
+ end
239
241
 
240
- yaml.extensions = %w(yaml yaml)
241
- assert_equal(%w(yaml), yaml.extensions)
242
+ it 'returns the set value when set' do
243
+ text_plain.encoding = '8bit'
244
+ assert_equal '8bit', text_plain.encoding
245
+ end
242
246
 
243
- yaml.extensions = %w(yz yaml yz yml)
244
- assert_equal(%w(yz yaml yml), yaml.extensions)
245
- end
247
+ it 'resets to the default encoding when set to nil or :default' do
248
+ text_plain.encoding = '8bit'
249
+ text_plain.encoding = nil
250
+ assert_equal text_plain.default_encoding, text_plain.encoding
251
+ text_plain.encoding = :default
252
+ assert_equal text_plain.default_encoding, text_plain.encoding
253
+ end
246
254
 
247
- def test_like_eh
248
- assert(MIME::Type.new('text/plain').like?(MIME::Type.new('text/plain')))
249
- assert(MIME::Type.new('text/plain').like?(MIME::Type.new('text/x-plain')))
250
- refute(MIME::Type.new('text/plain').like?(MIME::Type.new('image/jpeg')))
251
- assert(MIME::Type.new('text/plain').like?('text/plain'))
252
- assert(MIME::Type.new('text/plain').like?('text/x-plain'))
253
- refute(MIME::Type.new('text/plain').like?('image/jpeg'))
255
+ it 'raises a MIME::Type::InvalidEncoding for an invalid encoding' do
256
+ exception = assert_raises MIME::Type::InvalidEncoding do
257
+ text_plain.encoding = 'binary'
258
+ end
259
+ assert_equal 'Invalid Encoding "binary"', exception.to_s
260
+ end
254
261
  end
255
262
 
256
- def test_media_type
257
- assert_equal('text', MIME::Type.new('text/plain').media_type)
258
- assert_equal('image', MIME::Type.new('image/jpeg').media_type)
259
- assert_equal('application', MIME::Type.new('application/x-msword').media_type)
260
- assert_equal('text', MIME::Type.new('text/vCard').media_type)
261
- assert_equal('application', MIME::Type.new('application/pkcs7-mime').media_type)
262
- assert_equal('chemical', MIME::Type.new('x-chemical/x-pdb').media_type)
263
- assert_equal('appl', @applzip.media_type)
264
- end
263
+ describe '#eql?' do
264
+ it 'is not true for a non-MIME::Type' do
265
+ refute text_plain.eql?('text/plain')
266
+ end
265
267
 
266
- def test_obsolete_eh
267
- type = MIME::Type.new('content-type' => 'test/type',
268
- 'obsolete' => true)
269
- assert(type.obsolete?)
270
- refute(make_yaml_mime_type.obsolete?)
271
- end
268
+ it 'is not true for a different MIME::Type' do
269
+ refute text_plain.eql?(image_jpeg)
270
+ end
272
271
 
273
- def test_obsolete_equals
274
- yaml = make_yaml_mime_type
275
- refute(yaml.obsolete?)
276
- yaml.obsolete = true
277
- assert(yaml.obsolete?)
272
+ it 'is true for an equivalent MIME::Type' do
273
+ assert text_plain, mime_type('text/Plain')
274
+ end
278
275
  end
279
276
 
280
- def test_platform_eh
281
- assert_deprecated('MIME::Type#platform?') do
282
- refute make_yaml_mime_type.platform?
277
+ describe '#extensions, #extensions=' do
278
+ it 'returns an array of extensions' do
279
+ assert_equal %w(yaml yml), text_x_yaml.extensions
280
+ assert_equal %w(zip zp), x_appl_x_zip.extensions
281
+ end
282
+
283
+ it 'sets a single extension when provided a single value' do
284
+ text_x_yaml.extensions = 'yaml'
285
+ assert_equal %w(yaml), text_x_yaml.extensions
286
+ end
287
+
288
+ it 'deduplicates extensions' do
289
+ text_x_yaml.extensions = %w(yaml yaml)
290
+ assert_equal %w(yaml), text_x_yaml.extensions
283
291
  end
284
292
  end
285
293
 
286
- def assert_priority(l, e, r)
287
- assert_equal(-1, l.first.priority_compare(l.last))
288
- assert_equal(0, e.first.priority_compare(e.last))
289
- assert_equal(1, r.first.priority_compare(r.last))
294
+ describe '#add_extensions' do
295
+ it 'does not modify extensions when provided nil' do
296
+ text_x_yaml.add_extensions(nil)
297
+ assert_equal %w(yaml yml), text_x_yaml.extensions
298
+ end
299
+
300
+ it 'remains deduplicated with duplicate values' do
301
+ text_x_yaml.add_extensions('yaml')
302
+ assert_equal %w(yaml yml), text_x_yaml.extensions
303
+ text_x_yaml.add_extensions(%w(yaml yz))
304
+ assert_equal %w(yaml yml yz), text_x_yaml.extensions
305
+ end
290
306
  end
291
307
 
292
- def test_priority_compare
293
- tl, te, tr = make('text/1'), make('text/1'), make('text/2')
294
- assert_priority([tl, tr], [tl, te], [tr, tl])
308
+ describe '#priority_compare' do
309
+ def assert_priority_less(left, right)
310
+ assert_equal(-1, left.priority_compare(right))
311
+ end
295
312
 
296
- tl.registered = te.registered = true
297
- tr = make(tl) { |t| t.registered = false }
298
- assert_priority([tl, tr], [tl, te], [tr, tl])
313
+ def assert_priority_same(left, right)
314
+ assert_equal 0, left.priority_compare(right)
315
+ end
299
316
 
300
- tl.extensions = te.extensions = %w(1)
301
- tr = make(tl) { |t| t.extensions = nil }
302
- assert_priority([tl, tr], [tl, te], [tr, tl])
317
+ def assert_priority_more(left, right)
318
+ assert_equal 1, left.priority_compare(right)
319
+ end
303
320
 
304
- tl.obsolete = te.obsolete = false
305
- tr = make(tl) { |t| t.obsolete = true }
306
- assert_priority([tl, tr], [tl, te], [tr, tl])
321
+ def assert_priority(left, middle, right)
322
+ assert_priority_less left, right
323
+ assert_priority_same left, middle
324
+ assert_priority_more right, left
325
+ end
307
326
 
308
- tl.obsolete = te.obsolete = true
309
- tl.use_instead = te.use_instead = 'abc/xyz'
310
- tr = make(tl) { |t| t.use_instead = nil }
311
- assert_priority([tl, tr], [tl, te], [tr, tl])
312
- tr.use_instead = 'abc/zzz'
313
- assert_priority([tl, tr], [tl, te], [tr, tl])
314
- end
327
+ let(:text_1) { mime_type('text/1') }
328
+ let(:text_1p) { mime_type('text/1') }
329
+ let(:text_2) { mime_type('text/2') }
315
330
 
316
- def test_raw_media_type
317
- assert_equal('text', MIME::Type.new('text/plain').raw_media_type)
318
- assert_equal('image', MIME::Type.new('image/jpeg').raw_media_type)
319
- assert_equal('application', MIME::Type.new('application/x-msword').raw_media_type)
320
- assert_equal('text', MIME::Type.new('text/vCard').raw_media_type)
321
- assert_equal('application', MIME::Type.new('application/pkcs7-mime').raw_media_type)
322
- assert_equal('x-chemical', MIME::Type.new('x-chemical/x-pdb').raw_media_type)
323
- assert_equal('x-appl', @applzip.raw_media_type)
324
- end
331
+ it 'sorts (1) based on the simplified type' do
332
+ assert_priority text_1, text_1p, text_2
333
+ end
325
334
 
326
- def test_raw_sub_type
327
- assert_equal('plain', MIME::Type.new('text/plain').raw_sub_type)
328
- assert_equal('jpeg', MIME::Type.new('image/jpeg').raw_sub_type)
329
- assert_equal('x-msword', MIME::Type.new('application/x-msword').raw_sub_type)
330
- assert_equal('vCard', MIME::Type.new('text/vCard').raw_sub_type)
331
- assert_equal('pkcs7-mime', MIME::Type.new('application/pkcs7-mime').raw_sub_type)
332
- assert_equal('x-zip', @applzip.raw_sub_type)
333
- end
335
+ it 'sorts (2) based on extensions' do
336
+ text_1.extensions = ["foo", "bar"]
337
+ text_2.extensions = ["foo"]
334
338
 
335
- def test_registered_eh
336
- assert(MIME::Type.new('text/plain').registered?)
337
- assert(MIME::Type.new('image/jpeg').registered?)
338
- refute(MIME::Type.new('application/x-msword').registered?)
339
- assert(MIME::Type.new('text/vCard').registered?)
340
- assert(MIME::Type.new('application/pkcs7-mime').registered?)
341
- refute(@applzip.registered?)
342
- refute(MIME::Types['image/webp'].first.registered?)
343
- # Temporarily broken: requires the new data format to be enabled.
344
- assert(MIME::Types['application/x-www-form-urlencoded'].first.registered?)
345
- end
339
+ assert_priority_same text_1, text_2
346
340
 
347
- def test_registered_equals
348
- [ nil, false, true ].each { |v|
349
- @applzip.registered = v
350
- assert_equal(v, @applzip.instance_variable_get(:@registered))
351
- }
352
- @applzip.registered = 1
353
- assert_equal(true, @applzip.instance_variable_get(:@registered))
354
- end
341
+ text_2.registered = true
355
342
 
356
- def test_signature_eh
357
- refute(MIME::Type.new('text/plain').signature?)
358
- refute(MIME::Type.new('image/jpeg').signature?)
359
- refute(MIME::Type.new('application/x-msword').signature?)
360
- end
343
+ assert_priority_more text_1, text_2
344
+ end
361
345
 
362
- def test_signature_equals
363
- sig = MIME::Type.new('text/vCard') { |t| t.signature = true }
364
- assert(sig.signature?)
365
- end
346
+ it 'sorts (3) based on the registration state' do
347
+ text_1.registered = text_1p.registered = true
348
+ text_1b = mime_type(text_1) { |t| t.registered = false }
366
349
 
367
- def test_simplified
368
- assert_equal('text/plain', MIME::Type.new('text/plain').simplified)
369
- assert_equal('image/jpeg', MIME::Type.new('image/jpeg').simplified)
370
- assert_equal('application/msword', MIME::Type.new('application/x-msword').simplified)
371
- assert_equal('text/vcard', MIME::Type.new('text/vCard').simplified)
372
- assert_equal('application/pkcs7-mime', MIME::Type.new('application/pkcs7-mime').simplified)
373
- assert_equal('chemical/pdb', MIME::Type.new('x-chemical/x-pdb').simplified)
374
- end
350
+ assert_priority text_1, text_1p, text_1b
351
+ end
375
352
 
376
- def test_sub_type
377
- assert_equal('plain', MIME::Type.new('text/plain').sub_type)
378
- assert_equal('jpeg', MIME::Type.new('image/jpeg').sub_type)
379
- assert_equal('msword', MIME::Type.new('application/x-msword').sub_type)
380
- assert_equal('vcard', MIME::Type.new('text/vCard').sub_type)
381
- assert_equal('pkcs7-mime', MIME::Type.new('application/pkcs7-mime').sub_type)
382
- assert_equal('zip', @applzip.sub_type)
383
- end
353
+ it 'sorts (4) based on the completeness' do
354
+ text_1.extensions = text_1p.extensions = '1'
355
+ text_1b = mime_type(text_1) { |t| t.extensions = nil }
384
356
 
385
- def test_system
386
- assert_deprecated('MIME::Type#system') do
387
- assert_nil make_yaml_mime_type.system
357
+ assert_priority text_1, text_1p, text_1b
388
358
  end
389
- end
390
359
 
391
- def test_system_equals
392
- assert_deprecated('MIME::Type#system') do
393
- yaml = make_yaml_mime_type
394
- yaml.system = /win32/
395
- assert_nil yaml.system
360
+ it 'sorts (5) based on obsolete status' do
361
+ text_1.obsolete = text_1p.obsolete = false
362
+ text_1b = mime_type(text_1) { |t| t.obsolete = true }
363
+
364
+ assert_priority text_1, text_1p, text_1b
396
365
  end
397
- end
398
366
 
399
- def test_system_eh
400
- assert_deprecated('MIME::Type#system?') do
401
- refute make_yaml_mime_type.system?
367
+ it 'sorts (5) based on the use-instead value' do
368
+ text_1.obsolete = text_1p.obsolete = true
369
+ text_1.use_instead = text_1p.use_instead = 'abc/xyz'
370
+ text_1b = mime_type(text_1) { |t| t.use_instead = nil }
371
+
372
+ assert_priority text_1, text_1p, text_1b
373
+
374
+ text_1b.use_instead = 'abc/zzz'
375
+
376
+ assert_priority text_1, text_1p, text_1b
402
377
  end
403
378
  end
404
379
 
405
- def test_to_a
406
- yaml = make_yaml_mime_type
407
- assert_deprecated('MIME::Type#to_a') do
408
- assert_equal [ 'text/x-yaml', %w(yaml yml), '8bit', nil, false, [], [],
409
- false ], yaml.to_a
380
+ describe '#raw_media_type' do
381
+ it 'extracts the media type as case-preserved' do
382
+ assert_equal 'Text', mime_type('Text/plain').raw_media_type
410
383
  end
411
- end
412
384
 
413
- def test_to_hash
414
- yaml = make_yaml_mime_type
415
- assert_deprecated('MIME::Type#to_hash') do
416
- assert_equal(
417
- {
418
- 'Content-Type' => 'text/x-yaml',
419
- 'Content-Transfer-Encoding' => '8bit',
420
- 'Extensions' => %w(yaml yml),
421
- 'System' => nil,
422
- 'Registered' => false,
423
- 'URL' => [],
424
- 'Obsolete' => false,
425
- 'Docs' => []
426
- },
427
- yaml.to_hash)
385
+ it 'does not remove x- prefixes' do
386
+ assert_equal('x-appl', x_appl_x_zip.raw_media_type)
428
387
  end
429
388
  end
430
389
 
431
- def assert_type_has_keys(type, *keys)
432
- hash = type.to_h
433
- keys.flatten.each { |key| assert(hash.key?(key)) }
434
- end
390
+ describe '#media_type' do
391
+ it 'extracts the media type as lowercase' do
392
+ assert_equal 'text', text_plain.media_type
393
+ end
435
394
 
436
- def test_to_h
437
- t = make('a/b')
438
- assert_type_has_keys(t, %w(content-type registered encoding))
439
- assert_type_has_keys(make(t) { |v| v.docs = 'Something' }, 'docs')
440
- assert_type_has_keys(make(t) { |v| v.extensions = %w(b) }, 'extensions')
441
- assert_type_has_keys(make(t) { |v| v.obsolete = true }, 'obsolete')
442
- assert_type_has_keys(make(t) { |v|
443
- v.obsolete = true
444
- v.use_instead = 'c/d'
445
- }, 'obsolete', 'use-instead')
446
- assert_type_has_keys(make(t) { |v| v.signature = true }, 'signature')
395
+ it 'does not remove x- prefixes' do
396
+ assert_equal('x-appl', x_appl_x_zip.media_type)
397
+ end
447
398
  end
448
399
 
449
- def test_to_json
450
- assert_equal('{"content-type":"a/b","encoding":"base64","registered":true}',
451
- make('a/b').to_json)
400
+ describe '#raw_media_type' do
401
+ it 'extracts the media type as case-preserved' do
402
+ assert_equal 'Text', mime_type('Text/plain').raw_media_type
403
+ end
404
+
405
+ it 'does not remove x- prefixes' do
406
+ assert_equal('x-appl', x_appl_x_zip.raw_media_type)
407
+ end
452
408
  end
453
409
 
454
- def test_to_s
455
- assert_equal('text/plain', "#{MIME::Type.new('text/plain')}")
410
+ describe '#sub_type' do
411
+ it 'extracts the sub type as lowercase' do
412
+ assert_equal 'plain', text_plain.sub_type
413
+ end
414
+
415
+ it 'does not remove x- prefixes' do
416
+ assert_equal('x-zip', x_appl_x_zip.sub_type)
417
+ end
456
418
  end
457
419
 
458
- def test_class_constructors
459
- assert_instance_of(MIME::Type, MIME::Type.new('text/x-yaml'))
460
- assert_instance_of(MIME::Type, MIME::Type.new('text/x-yaml') { |y|
461
- assert_instance_of(MIME::Type, y)
462
- })
463
- assert_instance_of(MIME::Type, MIME::Type.new('content-type' => 'text/x-yaml'))
464
- assert_instance_of(MIME::Type, MIME::Type.new(['text/x-yaml', %w(yaml)]))
465
- assert_raises(MIME::Type::InvalidContentType) { MIME::Type.new('apps') }
466
- begin
467
- MIME::Type.new(nil)
468
- rescue MIME::Type::InvalidContentType => ex
469
- assert_equal('Invalid Content-Type nil', ex.message)
420
+ describe '#raw_sub_type' do
421
+ it 'extracts the sub type as case-preserved' do
422
+ assert_equal 'Plain', mime_type('text/Plain').raw_sub_type
423
+ end
424
+
425
+ it 'does not remove x- prefixes' do
426
+ assert_equal('x-zip', x_appl_x_zip.raw_sub_type)
470
427
  end
471
428
  end
472
429
 
473
- def test_to_str
474
- assert_equal('stringy', 'text/plain'.sub(MIME::Type.new('text/plain'), 'stringy'))
430
+ describe '#to_h' do
431
+ let(:t) { mime_type('a/b') }
432
+
433
+ it 'has the required keys (content-type, registered, encoding)' do
434
+ assert_has_keys t.to_h, %w(content-type registered encoding)
435
+ end
436
+
437
+ it 'has the docs key if there are documents' do
438
+ assert_has_keys mime_type(t) { |v| v.docs = 'a' }.to_h, %w(docs)
439
+ end
440
+
441
+ it 'has the extensions key if set' do
442
+ assert_has_keys mime_type(t) { |v| v.extensions = 'a' }.to_h,
443
+ 'extensions'
444
+ end
445
+
446
+ it 'has the preferred-extension key if set' do
447
+ assert_has_keys mime_type(t) { |v| v.preferred_extension = 'a' }.to_h,
448
+ 'preferred-extension'
449
+ end
450
+
451
+ it 'has the obsolete key if set' do
452
+ assert_has_keys mime_type(t) { |v| v.obsolete = true }.to_h, 'obsolete'
453
+ end
454
+
455
+ it 'has the obsolete and use-instead keys if set' do
456
+ assert_has_keys mime_type(t) { |v|
457
+ v.obsolete = true
458
+ v.use_instead = 'c/d'
459
+ }.to_h, %w(obsolete use-instead)
460
+ end
461
+
462
+ it 'has the signature key if set' do
463
+ assert_has_keys mime_type(t) { |v| v.signature = true }.to_h, 'signature'
464
+ end
475
465
  end
476
466
 
477
- def test_references
478
- assert_deprecated('MIME::Type#references') do
479
- assert_empty make_yaml_mime_type.references
467
+ describe '#to_json' do
468
+ let(:expected) {
469
+ '{"content-type":"a/b","encoding":"base64","registered":false}'
470
+ }
471
+
472
+ it 'converts to JSON when requested' do
473
+ assert_equal expected, mime_type('a/b').to_json
480
474
  end
481
475
  end
482
476
 
483
- def test_references_equals
484
- yaml = make_yaml_mime_type
485
- assert_deprecated('MIME::Type#references=') do
486
- yaml.references = :anything
477
+ describe '#to_s, #to_str' do
478
+ it 'represents itself as a string of the canonical content_type' do
479
+ assert_equal 'text/plain', "#{text_plain}"
487
480
  end
488
- assert_deprecated('MIME::Type#references') do
489
- assert_empty yaml.references
481
+
482
+ it 'acts like a string of the canonical content_type for comparison' do
483
+ assert_equal text_plain, 'text/plain'
490
484
  end
491
- end
492
485
 
493
- def test_xrefs
494
- assert_equal(
495
- {
496
- 'rfc' => %w(rfc4239),
497
- 'template' => %w(application/javascript)
498
- },
499
- make_javascript.xrefs
500
- )
486
+ it 'acts like a string for other purposes' do
487
+ assert_equal 'stringy', 'text/plain'.sub(text_plain, 'stringy')
488
+ end
501
489
  end
502
490
 
503
- def test_xref_urls
504
- js = make_javascript do |j|
505
- j.xrefs = j.xrefs.merge(
506
- 'draft' => [ 'RFC-ietf-appsawg-json-merge-patch-07' ],
507
- 'person' => [ 'David_Singer' ],
508
- 'rfc-errata' => [ '3245' ],
509
- 'uri' => [ 'http://exmple.org' ],
510
- 'text' => [ 'text' ]
511
- )
491
+ describe '#xrefs, #xrefs=' do
492
+ let(:expected) {
493
+ MIME::Types::Container.new({ 'rfc' => Set[*%w(rfc1234 rfc5678)] })
494
+ }
495
+
496
+ it 'returns the expected results' do
497
+ application_javascript.xrefs = {
498
+ 'rfc' => %w(rfc5678 rfc1234 rfc1234)
499
+ }
500
+
501
+ assert_equal expected, application_javascript.xrefs
512
502
  end
513
- assert_equal(
503
+ end
504
+
505
+ describe '#xref_urls' do
506
+ let(:expected) {
514
507
  [
515
- 'http://www.iana.org/go/rfc4239',
516
- 'http://www.iana.org/assignments/media-types/application/javascript',
517
- 'http://www.iana.org/go/draft-ietf-appsawg-json-merge-patch-07',
518
- 'http://www.iana.org/assignments/media-types/media-types.xhtml#David_Singer',
519
- 'http://www.rfc-editor.org/errata_search.php?eid=3245',
520
- 'http://exmple.org',
508
+ 'http://www.iana.org/go/draft1',
509
+ 'http://www.iana.org/assignments/media-types/a/b',
510
+ 'http://www.iana.org/assignments/media-types/media-types.xhtml#p-1',
511
+ 'http://www.iana.org/go/rfc-1',
512
+ 'http://www.rfc-editor.org/errata_search.php?eid=err-1',
513
+ 'http://example.org',
521
514
  'text'
522
- ],
523
- js.xref_urls
524
- )
525
- end
515
+ ]
516
+ }
517
+
518
+ let(:type) {
519
+ mime_type('a/b').tap do |t|
520
+ t.xrefs = {
521
+ 'draft' => [ 'RFC1' ],
522
+ 'template' => [ 'a/b' ],
523
+ 'person' => [ 'p-1' ],
524
+ 'rfc' => [ 'rfc-1' ],
525
+ 'rfc-errata' => [ 'err-1' ],
526
+ 'uri' => [ 'http://example.org' ],
527
+ 'text' => [ 'text' ]
528
+ }
529
+ end
530
+ }
526
531
 
527
- def test_url
528
- assert_deprecated('MIME::Type#url') do
529
- assert_empty(make_yaml_mime_type.url)
532
+ it 'translates according to given rules' do
533
+ assert_equal expected, type.xref_urls
530
534
  end
531
535
  end
532
536
 
533
- def test_url_equals
534
- yaml = make_yaml_mime_type
535
- assert_deprecated('MIME::Type#url=') do
536
- yaml.url = 'IANA'
537
+ describe '#use_instead' do
538
+ it 'is nil unless the type is obsolete' do
539
+ assert_nil text_plain.use_instead
537
540
  end
538
- assert_deprecated('MIME::Type#url') do
539
- assert_equal [], yaml.url
541
+
542
+ it 'is nil if not set and the type is obsolete' do
543
+ text_plain.obsolete = true
544
+ assert_nil text_plain.use_instead
540
545
  end
541
- end
542
546
 
543
- def test_urls
544
- yaml = make_yaml_mime_type
545
- assert_deprecated('MIME::Type#urls') do
546
- assert_empty yaml.urls
547
+ it 'is a different type if set and the type is obsolete' do
548
+ text_plain.obsolete = true
549
+ text_plain.use_instead = 'text/html'
550
+ assert_equal 'text/html', text_plain.use_instead
547
551
  end
548
552
  end
549
553
 
550
- def test_use_instead
551
- t = make('t/1') { |v| v.use_instead = 't/2' }
552
- assert_nil(t.use_instead)
553
- t.obsolete = true
554
- assert_equal('t/2', t.use_instead)
555
- end
554
+ describe '#preferred_extension, #preferred_extension=' do
555
+ it 'is nil when not set and there are no extensions' do
556
+ assert_nil text_plain.preferred_extension
557
+ end
556
558
 
557
- def test_use_instead_equals
558
- t = make('t/1') { |v| v.obsolete = true }
559
- assert_nil(t.use_instead)
560
- t.use_instead = 't/2'
561
- assert_equal('t/2', t.use_instead)
562
- end
559
+ it 'is the first extension when not set but there are extensions' do
560
+ assert_equal 'yaml', text_x_yaml.preferred_extension
561
+ end
563
562
 
564
- def test_preferred_extension
565
- assert_equal('zip', @applzip.preferred_extension)
566
- end
563
+ it 'is the extension provided when set' do
564
+ text_x_yaml.preferred_extension = 'yml'
565
+ assert_equal 'yml', text_x_yaml.preferred_extension
566
+ end
567
567
 
568
- def test_friendly_read
569
- yaml = make_yaml_mime_type
570
- assert_equal('YAML Structured Document', yaml.friendly)
571
- assert_equal('YAML Structured Document', yaml.friendly('en'))
572
- assert_equal(nil, yaml.friendly('fr'))
568
+ it 'is adds the preferred extension if it does not exist' do
569
+ text_x_yaml.preferred_extension = 'yz'
570
+ assert_equal 'yz', text_x_yaml.preferred_extension
571
+ assert_includes text_x_yaml.extensions, 'yz'
572
+ end
573
573
  end
574
574
 
575
- def test_friendly_set
576
- assert_equal({ 'en' => 'Zip' }, @applzip.friendly(%w(en Zip)))
577
- assert_equal({ 'en' => 'Zip Archive' }, @applzip.friendly('en' => 'Zip Archive'))
578
- end
575
+ describe '#friendly' do
576
+ it 'returns English by default' do
577
+ assert_equal 'YAML Structured Document', text_x_yaml.friendly
578
+ end
579
579
 
580
- def test_i18n_key
581
- assert_equal('text.plain', make('text/plain').i18n_key)
582
- assert_equal('application.vnd-3gpp-bsf-xml',
583
- make('application/vnd.3gpp.bsf+xml').i18n_key)
584
- assert_equal('application.msword', make('application/x-msword').i18n_key)
585
- end
580
+ it 'returns English when requested' do
581
+ assert_equal 'YAML Structured Document', text_x_yaml.friendly('en')
582
+ assert_equal 'YAML Structured Document', text_x_yaml.friendly(:en)
583
+ end
584
+
585
+ it 'returns nothing for an unknown language' do
586
+ assert_nil text_x_yaml.friendly('zz')
587
+ end
586
588
 
587
- def test_deprecated_constant
588
- assert_output(nil, /MIME::InvalidContentType/) do
589
- assert_same(MIME::InvalidContentType, MIME::Type::InvalidContentType)
589
+ it 'merges new values from an array parameter' do
590
+ expected = { 'en' => 'Text files' }
591
+ assert_equal expected, text_plain.friendly([ 'en', 'Text files' ])
592
+ expected.update('fr' => 'des fichiers texte')
593
+ assert_equal expected,
594
+ text_plain.friendly([ 'fr', 'des fichiers texte' ])
590
595
  end
591
- assert_output(nil, /MIME::InvalidContentType/) do
592
- assert_same(MIME::InvalidContentType, MIME::Type::InvalidContentType)
596
+
597
+ it 'merges new values from a hash parameter' do
598
+ expected = { 'en' => 'Text files' }
599
+ assert_equal expected, text_plain.friendly(expected)
600
+ french = { 'fr' => 'des fichiers texte' }
601
+ expected.update(french)
602
+ assert_equal expected, text_plain.friendly(french)
603
+ end
604
+
605
+ it 'raises an ArgumentError if an unknown value is provided' do
606
+ exception = assert_raises ArgumentError do
607
+ text_plain.friendly(1)
608
+ end
609
+
610
+ assert_equal 'Expected a language or translation set, not 1',
611
+ exception.message
593
612
  end
594
- assert_raises(NameError) { MIME::Foo }
595
613
  end
596
614
  end