mime-types 3.5.2 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,35 +2,55 @@
2
2
 
3
3
  require "mime/types/logger"
4
4
 
5
- # The namespace for MIME applications, tools, and libraries.
6
- module MIME
7
- ##
8
- class Types
9
- # Used to mark a method as deprecated in the mime-types interface.
10
- def self.deprecated(klass, sym, message = nil, &block) # :nodoc:
11
- level =
12
- case klass
5
+ class << MIME::Types
6
+ # Used to mark a method as deprecated in the mime-types interface.
7
+ def deprecated(options = {}, &block) # :nodoc:
8
+ message =
9
+ if options[:message]
10
+ options[:message]
11
+ else
12
+ klass = options.fetch(:class)
13
+
14
+ msep = case klass
13
15
  when Class, Module
14
16
  "."
15
17
  else
16
18
  klass = klass.class
17
19
  "#"
18
20
  end
19
- message =
20
- case message
21
+
22
+ method = "#{klass}#{msep}#{options.fetch(:method)}"
23
+ pre = " #{options[:pre]}" if options[:pre]
24
+ post = case options[:next]
21
25
  when :private, :protected
22
- "and will be #{message}"
23
- when nil
24
- "and will be removed"
26
+ " and will be made #{options[:next]}"
27
+ when :removed
28
+ " and will be removed"
29
+ when nil, ""
30
+ nil
25
31
  else
26
- message
32
+ " #{options[:next]}"
27
33
  end
28
- MIME::Types.logger.debug <<-WARNING.chomp.strip
29
- #{caller(2..2).first}: #{klass}#{level}#{sym} is deprecated #{message}.
30
- WARNING
31
34
 
32
- return unless block
33
- block.call
35
+ <<-WARNING.chomp.strip
36
+ #{caller(2..2).first}: #{klass}#{msep}#{method}#{pre} is deprecated#{post}.
37
+ WARNING
38
+ end
39
+
40
+ if !__deprecation_logged?(message, options[:once])
41
+ MIME::Types.logger.__send__(options[:level] || :debug, message)
34
42
  end
43
+
44
+ return unless block
45
+ block.call
46
+ end
47
+
48
+ private
49
+
50
+ def __deprecation_logged?(message, once)
51
+ return false unless once
52
+
53
+ @__deprecations_logged = {} unless defined?(@__deprecations_logged)
54
+ @__deprecations_logged.key?(message)
35
55
  end
36
56
  end
@@ -13,7 +13,7 @@ require "mime/types/data"
13
13
  #
14
14
  # The Loader will use one of the following paths:
15
15
  # 1. The +path+ provided in its constructor argument;
16
- # 2. The value of ENV['RUBY_MIME_TYPES_DATA']; or
16
+ # 2. The value of ENV["RUBY_MIME_TYPES_DATA"]; or
17
17
  # 3. The value of MIME::Types::Data::PATH.
18
18
  #
19
19
  # When #load is called, the +path+ will be searched recursively for all YAML
@@ -79,7 +79,7 @@ class MIME::Types::Loader
79
79
  #
80
80
  # This will load from columnar files (#load_columnar) if <tt>columnar:
81
81
  # true</tt> is provided in +options+ and there are columnar files in +path+.
82
- def load(options = {columnar: false})
82
+ def load(options = {columnar: true})
83
83
  if options[:columnar] && !Dir[columnar_path].empty?
84
84
  load_columnar
85
85
  else
@@ -9,7 +9,18 @@ module MIME
9
9
  class << self
10
10
  # Configure the MIME::Types logger. This defaults to an instance of a
11
11
  # logger that passes messages (unformatted) through to Kernel#warn.
12
- attr_accessor :logger
12
+ # :attr_accessor: logger
13
+ attr_reader :logger
14
+
15
+ ##
16
+ def logger=(logger) # :nodoc
17
+ @logger =
18
+ if logger.nil?
19
+ NullLogger.new
20
+ else
21
+ logger
22
+ end
23
+ end
13
24
  end
14
25
 
15
26
  class WarnLogger < ::Logger # :nodoc:
@@ -25,13 +36,33 @@ module MIME
25
36
  end
26
37
  end
27
38
 
28
- def initialize(_one, _two = nil, _three = nil)
39
+ def initialize(*)
29
40
  super(nil)
30
41
  @logdev = WarnLogDevice.new
31
42
  @formatter = ->(_s, _d, _p, m) { m }
32
43
  end
33
44
  end
34
45
 
35
- self.logger = WarnLogger.new(nil)
46
+ class NullLogger < ::Logger
47
+ def initialize(*)
48
+ super(nil)
49
+ @logdev = nil
50
+ end
51
+
52
+ def reopen(_)
53
+ self
54
+ end
55
+
56
+ def <<(_)
57
+ end
58
+
59
+ def close
60
+ end
61
+
62
+ def add(_severity, _message = nil, _progname = nil)
63
+ end
64
+ end
65
+
66
+ self.logger = WarnLogger.new
36
67
  end
37
68
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "mime/types/deprecations"
4
+
3
5
  class << MIME::Types
4
6
  include Enumerable
5
7
 
@@ -45,11 +47,11 @@ class << MIME::Types
45
47
  def lazy_load?
46
48
  return unless ENV.key?("RUBY_MIME_TYPES_LAZY_LOAD")
47
49
 
48
- MIME::Types.logger.debug <<-WARNING.chomp.strip
49
- Lazy loading ($RUBY_MIME_TYPES_LAZY_LOAD) is deprecated and will be removed.
50
- WARNING
50
+ deprecated(
51
+ message: "Lazy loading ($RUBY_MIME_TYPES_LAZY_LOAD) is deprecated and will be removed."
52
+ )
51
53
 
52
- (lazy = ENV["RUBY_MIME_TYPES_LAZY_LOAD"]) && (lazy != "false")
54
+ ENV["RUBY_MIME_TYPES_LAZY_LOAD"] != "false"
53
55
  end
54
56
 
55
57
  def __types__
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ module MIME
5
+ class Types
6
+ # The released version of the mime-types library.
7
+ VERSION = "3.7.0"
8
+ end
9
+
10
+ class Type
11
+ # The released version of the mime-types library.
12
+ VERSION = MIME::Types::VERSION
13
+ end
14
+ end
data/lib/mime/types.rb CHANGED
@@ -66,9 +66,6 @@ require "mime/type"
66
66
  # puts MIME::Type.simplified('x-appl/x-zip') # => 'appl/zip'
67
67
  #
68
68
  class MIME::Types
69
- # The release version of Ruby MIME::Types
70
- VERSION = MIME::Type::VERSION
71
-
72
69
  include Enumerable
73
70
 
74
71
  # Creates a new MIME::Types registry.
@@ -133,9 +130,7 @@ class MIME::Types
133
130
  @type_variants[MIME::Type.simplified(type_id)]
134
131
  end
135
132
 
136
- prune_matches(matches, complete, registered).sort { |a, b|
137
- a.priority_compare(b)
138
- }
133
+ prune_matches(matches, complete, registered).sort
139
134
  end
140
135
 
141
136
  # Return the list of MIME::Types which belongs to the file based on its
@@ -151,10 +146,14 @@ class MIME::Types
151
146
  # puts MIME::Types.type_for(%w(citydesk.xml citydesk.gif))
152
147
  # => [application/xml, image/gif, text/xml]
153
148
  def type_for(filename)
154
- Array(filename).flat_map { |fn|
155
- @extension_index[fn.chomp.downcase[/\.?([^.]*?)\z/m, 1]]
156
- }.compact.inject(Set.new, :+).sort { |a, b|
157
- a.priority_compare(b)
149
+ wanted = Array(filename).map { |fn| fn.chomp.downcase[/\.?([^.]*?)\z/m, 1] }
150
+
151
+ wanted
152
+ .flat_map { |ext| @extension_index[ext] }
153
+ .compact
154
+ .reduce(Set.new, :+)
155
+ .sort { |a, b|
156
+ a.__extension_priority_compare(b, wanted)
158
157
  }
159
158
  end
160
159
  alias_method :of, :type_for
@@ -196,6 +195,10 @@ class MIME::Types
196
195
  index_extensions!(type)
197
196
  end
198
197
 
198
+ def __fully_loaded? # :nodoc:
199
+ true
200
+ end
201
+
199
202
  private
200
203
 
201
204
  def add_type_variant!(mime_type)
@@ -223,6 +226,12 @@ class MIME::Types
223
226
  k =~ pattern
224
227
  }.values.inject(Set.new, :+)
225
228
  end
229
+
230
+ # def stable_sort(list)
231
+ # list.lazy.each_with_index.sort { |(a, ai), (b, bi)|
232
+ # a.priority_compare(b).nonzero? || ai <=> bi
233
+ # }.map(&:first)
234
+ # end
226
235
  end
227
236
 
228
237
  require "mime/types/cache"
@@ -231,3 +240,4 @@ require "mime/types/loader"
231
240
  require "mime/types/logger"
232
241
  require "mime/types/_columnar"
233
242
  require "mime/types/registry"
243
+ require "mime/types/version"
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "mime/type"
4
- require "fileutils"
5
-
6
3
  gem "minitest"
7
4
  require "minitest/focus"
8
5
  require "minitest/hooks"
9
6
 
7
+ require "fileutils"
8
+
9
+ require "mime/type"
10
10
  ENV["RUBY_MIME_TYPES_LAZY_LOAD"] = "yes"
@@ -9,13 +9,13 @@ describe MIME::Type do
9
9
  end
10
10
 
11
11
  let(:x_appl_x_zip) {
12
- mime_type("x-appl/x-zip") { |t| t.extensions = %w[zip zp] }
12
+ mime_type("content-type" => "x-appl/x-zip") { |t| t.extensions = %w[zip zp] }
13
13
  }
14
- let(:text_plain) { mime_type("text/plain") }
15
- let(:text_html) { mime_type("text/html") }
16
- let(:image_jpeg) { mime_type("image/jpeg") }
14
+ let(:text_plain) { mime_type("content-type" => "text/plain") }
15
+ let(:text_html) { mime_type("content-type" => "text/html") }
16
+ let(:image_jpeg) { mime_type("content-type" => "image/jpeg") }
17
17
  let(:application_javascript) {
18
- mime_type("application/javascript") do |js|
18
+ mime_type("content-type" => "application/javascript") do |js|
19
19
  js.friendly("en" => "JavaScript")
20
20
  js.xrefs = {
21
21
  "rfc" => %w[rfc4239 rfc4239],
@@ -27,7 +27,7 @@ describe MIME::Type do
27
27
  end
28
28
  }
29
29
  let(:text_x_yaml) {
30
- mime_type("text/x-yaml") do |yaml|
30
+ mime_type("content-type" => "text/x-yaml") do |yaml|
31
31
  yaml.extensions = %w[yaml yml]
32
32
  yaml.encoding = "8bit"
33
33
  yaml.friendly("en" => "YAML Structured Document")
@@ -88,20 +88,22 @@ describe MIME::Type do
88
88
  describe ".new" do
89
89
  it "fails if an invalid content type is provided" do
90
90
  exception = assert_raises MIME::Type::InvalidContentType do
91
- MIME::Type.new("apps")
91
+ MIME::Type.new("content-type" => "apps")
92
92
  end
93
93
  assert_equal 'Invalid Content-Type "apps"', exception.to_s
94
94
  end
95
95
 
96
96
  it "creates a valid content type just from a string" do
97
- type = MIME::Type.new("text/x-yaml")
97
+ assert_output "", /MIME::Type.new when called with a String is deprecated\./ do
98
+ type = MIME::Type.new("text/x-yaml")
98
99
 
99
- assert_instance_of MIME::Type, type
100
- assert_equal "text/x-yaml", type.content_type
100
+ assert_instance_of MIME::Type, type
101
+ assert_equal "text/x-yaml", type.content_type
102
+ end
101
103
  end
102
104
 
103
105
  it "yields the content type in a block" do
104
- MIME::Type.new("text/x-yaml") do |type|
106
+ MIME::Type.new("content-type" => "text/x-yaml") do |type|
105
107
  assert_instance_of MIME::Type, type
106
108
  assert_equal "text/x-yaml", type.content_type
107
109
  end
@@ -118,10 +120,12 @@ describe MIME::Type do
118
120
  end
119
121
 
120
122
  it "creates a valid content type from an array" do
121
- type = MIME::Type.new(%w[text/x-yaml yaml yml yz])
122
- assert_instance_of MIME::Type, type
123
- assert_equal "text/x-yaml", type.content_type
124
- assert_equal %w[yaml yml yz], type.extensions
123
+ assert_output "", /MIME::Type.new when called with an Array is deprecated\./ do
124
+ type = MIME::Type.new(%w[text/x-yaml yaml yml yz])
125
+ assert_instance_of MIME::Type, type
126
+ assert_equal "text/x-yaml", type.content_type
127
+ assert_equal %w[yaml yml yz], type.extensions
128
+ end
125
129
  end
126
130
  end
127
131
 
@@ -143,7 +147,7 @@ describe MIME::Type do
143
147
  end
144
148
 
145
149
  it "correctly compares equivalent types" do
146
- right = mime_type("text/Plain")
150
+ right = mime_type("content-type" => "text/Plain")
147
151
  refute_same text_plain, right
148
152
  assert_equal text_plain, right
149
153
  end
@@ -171,11 +175,6 @@ describe MIME::Type do
171
175
  refute_equal text_plain, "text/html"
172
176
  assert_operator text_plain, :>, "text/html"
173
177
  end
174
-
175
- it "correctly compares against nil" do
176
- refute_equal text_html, nil
177
- assert_operator text_plain, :<, nil
178
- end
179
178
  end
180
179
 
181
180
  describe "#ascii?" do
@@ -204,14 +203,14 @@ describe MIME::Type do
204
203
  end
205
204
 
206
205
  it "is false when there are no extensions" do
207
- refute mime_type("text/plain").complete?
206
+ refute mime_type("content-type" => "text/plain").complete?
208
207
  end
209
208
  end
210
209
 
211
210
  describe "#content_type" do
212
211
  it "preserves the original case" do
213
212
  assert_equal "text/plain", text_plain.content_type
214
- assert_equal "text/vCard", mime_type("text/vCard").content_type
213
+ assert_equal "text/vCard", mime_type("content-type" => "text/vCard").content_type
215
214
  end
216
215
 
217
216
  it "does not remove x- prefixes" do
@@ -266,27 +265,27 @@ describe MIME::Type do
266
265
  end
267
266
 
268
267
  it "is true for an equivalent MIME::Type" do
269
- assert text_plain.eql?(mime_type("text/Plain"))
268
+ assert text_plain.eql?(mime_type("content-type" => "text/Plain"))
270
269
  end
271
270
 
272
271
  it "is true for an equivalent subclass of MIME::Type" do
273
272
  subclass = Class.new(MIME::Type)
274
- assert text_plain.eql?(subclass.new("text/plain"))
273
+ assert text_plain.eql?(subclass.new("content-type" => "text/plain"))
275
274
  end
276
275
  end
277
276
 
278
277
  describe "#hash" do
279
278
  it "is the same between #eql? MIME::Type instances" do
280
- assert_equal text_plain.hash, mime_type("text/plain").hash
279
+ assert_equal text_plain.hash, mime_type("content-type" => "text/plain").hash
281
280
  end
282
281
 
283
282
  it "is the same between #eql? MIME::Type instances of different classes" do
284
283
  subclass = Class.new(MIME::Type)
285
- assert_equal text_plain.hash, subclass.new("text/plain").hash
284
+ assert_equal text_plain.hash, subclass.new("content-type" => "text/plain").hash
286
285
  end
287
286
 
288
287
  it "uses the #simplified value" do
289
- assert_equal text_plain.hash, mime_type("text/Plain").hash
288
+ assert_equal text_plain.hash, mime_type("content-type" => "text/Plain").hash
290
289
  end
291
290
  end
292
291
 
@@ -322,41 +321,56 @@ describe MIME::Type do
322
321
  end
323
322
 
324
323
  describe "#priority_compare" do
324
+ def priority(type)
325
+ priority = "OpRceXtN"
326
+ .chars
327
+ .zip(("%08b" % type.__sort_priority).chars)
328
+ .map { |e| e.join(":") }
329
+ .join(" ")
330
+
331
+ "#{type} (#{priority} / #{type.__sort_priority})"
332
+ end
333
+
325
334
  def assert_priority_less(left, right)
326
- assert_equal(-1, left.priority_compare(right))
335
+ assert_equal(-1, left.priority_compare(right), "#{priority(left)} is not less than #{priority(right)}")
327
336
  end
328
337
 
329
338
  def assert_priority_same(left, right)
330
- assert_equal 0, left.priority_compare(right)
339
+ assert_equal 0, left.priority_compare(right), "#{priority(left)} is not equal to #{priority(right)}"
331
340
  end
332
341
 
333
342
  def assert_priority_more(left, right)
334
- assert_equal 1, left.priority_compare(right)
343
+ assert_equal 1, left.priority_compare(right), "#{priority(left)} is not more than #{priority(right)}"
335
344
  end
336
345
 
337
346
  def assert_priority(left, middle, right)
338
347
  assert_priority_less left, right
339
348
  assert_priority_same left, middle
340
- assert_priority_more right, left
349
+ assert_priority_more right, middle
341
350
  end
342
351
 
343
- let(:text_1) { mime_type("text/1") }
344
- let(:text_1p) { mime_type("text/1") }
345
- let(:text_2) { mime_type("text/2") }
352
+ let(:text_1) { mime_type("content-type" => "text/1") }
353
+ let(:text_1p) { mime_type("content-type" => "text/1") }
354
+ let(:text_2) { mime_type("content-type" => "text/2") }
346
355
 
347
- it "sorts (1) based on the simplified type" do
356
+ it "sorts based on the simplified type when the sort priorities are the same" do
348
357
  assert_priority text_1, text_1p, text_2
349
358
  end
350
359
 
351
- it "sorts (2) based on extensions" do
352
- text_1.extensions = ["foo", "bar"]
353
- text_2.extensions = ["foo"]
360
+ it "sorts obsolete types higher than non-obsolete types" do
361
+ text_1.obsolete = text_1p.obsolete = false
362
+ text_1b = mime_type(text_1) { |t| t.obsolete = true }
354
363
 
355
- assert_priority_same text_1, text_2
364
+ assert_priority_less text_1, text_1b
356
365
 
357
- text_2.registered = true
366
+ assert_priority text_1, text_1p, text_1b
367
+ end
358
368
 
359
- assert_priority_more text_1, text_2
369
+ it "sorts provisional types higher than non-provisional types" do
370
+ text_1.provisional = text_1p.provisional = false
371
+ text_1b = mime_type(text_1) { |t| t.provisional = true }
372
+
373
+ assert_priority text_1, text_1p, text_1b
360
374
  end
361
375
 
362
376
  it "sorts (3) based on the registration state" do
@@ -373,29 +387,17 @@ describe MIME::Type do
373
387
  assert_priority text_1, text_1p, text_1b
374
388
  end
375
389
 
376
- it "sorts (5) based on obsolete status" do
377
- text_1.obsolete = text_1p.obsolete = false
378
- text_1b = mime_type(text_1) { |t| t.obsolete = true }
379
-
380
- assert_priority text_1, text_1p, text_1b
381
- end
382
-
383
- it "sorts (5) based on the use-instead value" do
384
- text_1.obsolete = text_1p.obsolete = true
385
- text_1.use_instead = text_1p.use_instead = "abc/xyz"
386
- text_1b = mime_type(text_1) { |t| t.use_instead = nil }
387
-
388
- assert_priority text_1, text_1p, text_1b
389
-
390
- text_1b.use_instead = "abc/zzz"
390
+ it "sorts based on extensions (more extensions sort lower)" do
391
+ text_1.extensions = ["foo", "bar"]
392
+ text_2.extensions = ["foo"]
391
393
 
392
- assert_priority text_1, text_1p, text_1b
394
+ assert_priority_less text_1, text_2
393
395
  end
394
396
  end
395
397
 
396
398
  describe "#raw_media_type" do
397
399
  it "extracts the media type as case-preserved" do
398
- assert_equal "Text", mime_type("Text/plain").raw_media_type
400
+ assert_equal "Text", mime_type("content-type" => "Text/plain").raw_media_type
399
401
  end
400
402
 
401
403
  it "does not remove x- prefixes" do
@@ -415,7 +417,7 @@ describe MIME::Type do
415
417
 
416
418
  describe "#raw_media_type" do
417
419
  it "extracts the media type as case-preserved" do
418
- assert_equal "Text", mime_type("Text/plain").raw_media_type
420
+ assert_equal "Text", mime_type("content-type" => "Text/plain").raw_media_type
419
421
  end
420
422
 
421
423
  it "does not remove x- prefixes" do
@@ -435,7 +437,7 @@ describe MIME::Type do
435
437
 
436
438
  describe "#raw_sub_type" do
437
439
  it "extracts the sub type as case-preserved" do
438
- assert_equal "Plain", mime_type("text/Plain").raw_sub_type
440
+ assert_equal "Plain", mime_type("content-type" => "text/Plain").raw_sub_type
439
441
  end
440
442
 
441
443
  it "does not remove x- prefixes" do
@@ -444,7 +446,7 @@ describe MIME::Type do
444
446
  end
445
447
 
446
448
  describe "#to_h" do
447
- let(:t) { mime_type("a/b") }
449
+ let(:t) { mime_type("content-type" => "a/b") }
448
450
 
449
451
  def assert_has_keys(wanted_keys, actual, msg = nil)
450
452
  wanted_keys = Array(wanted_keys).uniq.sort
@@ -498,18 +500,18 @@ describe MIME::Type do
498
500
 
499
501
  describe "#to_json" do
500
502
  let(:expected_1) {
501
- '{"content-type":"a/b","encoding":"base64","registered":false}'
503
+ '{"content-type":"a/b","encoding":"base64","registered":false,"sort-priority":48}'
502
504
  }
503
505
  let(:expected_2) {
504
- '{"content-type":"a/b","encoding":"base64","registered":true,"provisional":true}'
506
+ '{"content-type":"a/b","encoding":"base64","registered":true,"provisional":true,"sort-priority":80}'
505
507
  }
506
508
 
507
509
  it "converts to JSON when requested" do
508
- assert_equal expected_1, mime_type("a/b").to_json
510
+ assert_equal expected_1, mime_type("content-type" => "a/b").to_json
509
511
  end
510
512
 
511
513
  it "converts to JSON with provisional when requested" do
512
- type = mime_type("a/b") do |t|
514
+ type = mime_type("content-type" => "a/b") do |t|
513
515
  t.registered = true
514
516
  t.provisional = true
515
517
  end
@@ -559,7 +561,7 @@ describe MIME::Type do
559
561
  }
560
562
 
561
563
  let(:type) {
562
- mime_type("a/b").tap do |t|
564
+ mime_type("content-type" => "a/b").tap do |t|
563
565
  t.xrefs = {
564
566
  "draft" => ["RFC1"],
565
567
  "template" => ["a/b"],
@@ -6,19 +6,15 @@ require "minitest_helper"
6
6
  describe MIME::Types do
7
7
  def mime_types
8
8
  @mime_types ||= MIME::Types.new.tap { |mt|
9
- mt.add MIME::Type.new(["text/plain", %w[txt]]),
10
- MIME::Type.new(["image/jpeg", %w[jpg jpeg]]),
11
- MIME::Type.new("application/x-wordperfect6.1"),
12
- MIME::Type.new(
13
- "content-type" => "application/x-www-form-urlencoded",
14
- "registered" => true
15
- ),
16
- MIME::Type.new(["application/x-gzip", %w[gz]]),
17
- MIME::Type.new(
18
- "content-type" => "application/gzip",
19
- "extensions" => "gz",
20
- "registered" => true
21
- )
9
+ mt.add(
10
+ MIME::Type.new("content-type" => "text/plain", "extensions" => %w[txt]),
11
+ MIME::Type.new("content-type" => "image/jpeg", "extensions" => %w[jpg jpeg]),
12
+ MIME::Type.new("content-type" => "application/x-wordperfect6.1"),
13
+ MIME::Type.new("content-type" => "application/x-www-form-urlencoded", "registered" => true),
14
+ MIME::Type.new("content-type" => "application/x-gzip", "extensions" => %w[gz]),
15
+ MIME::Type.new("content-type" => "application/gzip", "extensions" => "gz", "registered" => true),
16
+ *MIME::Types.type_for("foo.webm")
17
+ )
22
18
  }
23
19
  end
24
20
 
@@ -38,14 +34,14 @@ describe MIME::Types do
38
34
  end
39
35
 
40
36
  it "is countable with an enumerator" do
41
- assert_equal 6, mime_types.each.count
42
- assert_equal 6, mime_types.lazy.count
37
+ assert_equal 8, mime_types.each.count
38
+ assert_equal 8, mime_types.lazy.count
43
39
  end
44
40
  end
45
41
 
46
42
  describe "#[]" do
47
43
  it "can be searched with a MIME::Type" do
48
- text_plain = MIME::Type.new("text/plain")
44
+ text_plain = MIME::Type.new("content-type" => "text/plain")
49
45
  assert_includes mime_types[text_plain], "text/plain"
50
46
  assert_equal 1, mime_types[text_plain].size
51
47
  end
@@ -92,8 +88,8 @@ describe MIME::Types do
92
88
  end
93
89
 
94
90
  describe "#add" do
95
- let(:eruby) { MIME::Type.new("application/x-eruby") }
96
- let(:jinja) { MIME::Type.new("application/jinja2") }
91
+ let(:eruby) { MIME::Type.new("content-type" => "application/x-eruby") }
92
+ let(:jinja) { MIME::Type.new("content-type" => "application/jinja2") }
97
93
 
98
94
  it "successfully adds a new type" do
99
95
  mime_types.add(eruby)
@@ -144,7 +140,7 @@ describe MIME::Types do
144
140
  end
145
141
 
146
142
  it "finds multiple extensions" do
147
- assert_equal %w[image/jpeg text/plain],
143
+ assert_equal %w[text/plain image/jpeg],
148
144
  mime_types.type_for(%w[foo.txt foo.jpeg])
149
145
  end
150
146
 
@@ -163,11 +159,15 @@ describe MIME::Types do
163
159
  it "handles newline characters correctly" do
164
160
  assert_includes mime_types.type_for("test.pdf\n.txt"), "text/plain"
165
161
  end
162
+
163
+ it "returns a stable order for types with equal priority" do
164
+ assert_equal %w[text/x-vcalendar text/x-vcard], MIME::Types[/text\/x-vca/]
165
+ end
166
166
  end
167
167
 
168
168
  describe "#count" do
169
169
  it "can count the number of types inside" do
170
- assert_equal 6, mime_types.count
170
+ assert_equal 8, mime_types.count
171
171
  end
172
172
  end
173
173
  end