mime-types 3.3.1 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +413 -0
- data/CODE_OF_CONDUCT.md +128 -0
- data/CONTRIBUTING.md +93 -0
- data/CONTRIBUTORS.md +52 -0
- data/{Licence.md → LICENCE.md} +11 -12
- data/Manifest.txt +8 -5
- data/README.md +200 -0
- data/Rakefile +118 -201
- data/SECURITY.md +7 -0
- data/lib/mime/type/columnar.rb +17 -4
- data/lib/mime/type.rb +293 -134
- data/lib/mime/types/_columnar.rb +72 -24
- data/lib/mime/types/cache.rb +8 -12
- data/lib/mime/types/columnar.rb +1 -1
- data/lib/mime/types/container.rb +49 -19
- data/lib/mime/types/deprecations.rb +51 -27
- data/lib/mime/types/full.rb +2 -2
- data/lib/mime/types/loader.rb +29 -16
- data/lib/mime/types/logger.rb +38 -9
- data/lib/mime/types/registry.rb +10 -8
- data/lib/mime/types/version.rb +14 -0
- data/lib/mime/types.rb +45 -33
- data/lib/mime-types.rb +1 -1
- data/test/minitest_helper.rb +6 -9
- data/test/test_mime_type.rb +337 -288
- data/test/test_mime_types.rb +79 -75
- data/test/test_mime_types_cache.rb +38 -38
- data/test/test_mime_types_class.rb +70 -59
- data/test/test_mime_types_lazy.rb +16 -16
- data/test/test_mime_types_loader.rb +14 -14
- metadata +54 -122
- data/Code-of-Conduct.md +0 -73
- data/Contributing.md +0 -143
- data/History.md +0 -240
- data/README.rdoc +0 -193
data/test/test_mime_type.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "mime/types"
|
|
4
|
+
require "minitest_helper"
|
|
5
5
|
|
|
6
6
|
describe MIME::Type do
|
|
7
7
|
def mime_type(content_type)
|
|
@@ -9,602 +9,651 @@ describe MIME::Type do
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
let(:x_appl_x_zip) {
|
|
12
|
-
mime_type(
|
|
12
|
+
mime_type("content-type" => "x-appl/x-zip") { |t| t.extensions = %w[zip zp] }
|
|
13
13
|
}
|
|
14
|
-
let(:text_plain) { mime_type(
|
|
15
|
-
let(:text_html) { mime_type(
|
|
16
|
-
let(:image_jpeg) { mime_type(
|
|
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(
|
|
19
|
-
js.friendly(
|
|
18
|
+
mime_type("content-type" => "application/javascript") do |js|
|
|
19
|
+
js.friendly("en" => "JavaScript")
|
|
20
20
|
js.xrefs = {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
"rfc" => %w[rfc4239 rfc4239],
|
|
22
|
+
"template" => %w[application/javascript]
|
|
23
23
|
}
|
|
24
|
-
js.encoding =
|
|
25
|
-
js.extensions = %w
|
|
24
|
+
js.encoding = "8bit"
|
|
25
|
+
js.extensions = %w[js sj]
|
|
26
26
|
js.registered = true
|
|
27
27
|
end
|
|
28
28
|
}
|
|
29
29
|
let(:text_x_yaml) {
|
|
30
|
-
mime_type(
|
|
31
|
-
yaml.extensions = %w
|
|
32
|
-
yaml.encoding
|
|
33
|
-
yaml.friendly(
|
|
30
|
+
mime_type("content-type" => "text/x-yaml") do |yaml|
|
|
31
|
+
yaml.extensions = %w[yaml yml]
|
|
32
|
+
yaml.encoding = "8bit"
|
|
33
|
+
yaml.friendly("en" => "YAML Structured Document")
|
|
34
34
|
end
|
|
35
35
|
}
|
|
36
36
|
let(:text_x_yaml_with_docs) {
|
|
37
37
|
text_x_yaml.dup.tap do |yaml|
|
|
38
|
-
yaml.docs =
|
|
38
|
+
yaml.docs = "Test YAML"
|
|
39
39
|
end
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
describe
|
|
43
|
-
it
|
|
44
|
-
assert_equal
|
|
42
|
+
describe ".simplified" do
|
|
43
|
+
it "leaves normal types alone" do
|
|
44
|
+
assert_equal "text/plain", MIME::Type.simplified("text/plain")
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
it
|
|
48
|
-
assert_equal
|
|
49
|
-
|
|
50
|
-
assert_equal
|
|
47
|
+
it "does not remove x- prefixes by default" do
|
|
48
|
+
assert_equal "application/x-msword",
|
|
49
|
+
MIME::Type.simplified("application/x-msword")
|
|
50
|
+
assert_equal "x-xyz/abc", MIME::Type.simplified("x-xyz/abc")
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
it
|
|
54
|
-
assert_equal
|
|
55
|
-
|
|
56
|
-
assert_equal
|
|
57
|
-
|
|
53
|
+
it "removes x- prefixes when requested" do
|
|
54
|
+
assert_equal "application/msword",
|
|
55
|
+
MIME::Type.simplified("application/x-msword", remove_x_prefix: true)
|
|
56
|
+
assert_equal "xyz/abc",
|
|
57
|
+
MIME::Type.simplified("x-xyz/abc", remove_x_prefix: true)
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
it
|
|
61
|
-
assert_equal
|
|
60
|
+
it "lowercases mixed-case types" do
|
|
61
|
+
assert_equal "text/vcard", MIME::Type.simplified("text/vCard")
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
it
|
|
65
|
-
assert_nil MIME::Type.simplified(
|
|
64
|
+
it "returns nil when the value provided is not a valid content type" do
|
|
65
|
+
assert_nil MIME::Type.simplified("text")
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
describe
|
|
70
|
-
it
|
|
71
|
-
assert_equal
|
|
69
|
+
describe ".i18n_key" do
|
|
70
|
+
it "converts text/plain to text.plain" do
|
|
71
|
+
assert_equal "text.plain", MIME::Type.i18n_key("text/plain")
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
it
|
|
75
|
-
assert_equal
|
|
76
|
-
|
|
74
|
+
it "does not remove x-prefixes" do
|
|
75
|
+
assert_equal "application.x-msword",
|
|
76
|
+
MIME::Type.i18n_key("application/x-msword")
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
it
|
|
80
|
-
assert_equal
|
|
79
|
+
it "converts text/vCard to text.vcard" do
|
|
80
|
+
assert_equal "text.vcard", MIME::Type.i18n_key("text/vCard")
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
it
|
|
84
|
-
assert_nil MIME::Type.i18n_key(
|
|
83
|
+
it "returns nil when the value provided is not a valid content type" do
|
|
84
|
+
assert_nil MIME::Type.i18n_key("text")
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
-
describe
|
|
89
|
-
it
|
|
88
|
+
describe ".new" do
|
|
89
|
+
it "fails if an invalid content type is provided" do
|
|
90
90
|
exception = assert_raises MIME::Type::InvalidContentType do
|
|
91
|
-
MIME::Type.new(
|
|
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
|
-
it
|
|
97
|
-
|
|
96
|
+
it "creates a valid content type just from a string" do
|
|
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
|
-
|
|
100
|
-
|
|
100
|
+
assert_instance_of MIME::Type, type
|
|
101
|
+
assert_equal "text/x-yaml", type.content_type
|
|
102
|
+
end
|
|
101
103
|
end
|
|
102
104
|
|
|
103
|
-
it
|
|
104
|
-
MIME::Type.new(
|
|
105
|
+
it "yields the content type in a block" do
|
|
106
|
+
MIME::Type.new("content-type" => "text/x-yaml") do |type|
|
|
105
107
|
assert_instance_of MIME::Type, type
|
|
106
|
-
assert_equal
|
|
108
|
+
assert_equal "text/x-yaml", type.content_type
|
|
107
109
|
end
|
|
108
110
|
end
|
|
109
111
|
|
|
110
|
-
it
|
|
112
|
+
it "creates a valid content type from a hash" do
|
|
111
113
|
type = MIME::Type.new(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
"content-type" => "text/x-yaml",
|
|
115
|
+
"obsolete" => true
|
|
114
116
|
)
|
|
115
117
|
assert_instance_of MIME::Type, type
|
|
116
|
-
assert_equal
|
|
118
|
+
assert_equal "text/x-yaml", type.content_type
|
|
117
119
|
assert type.obsolete?
|
|
118
120
|
end
|
|
119
121
|
|
|
120
|
-
it
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
it "creates a valid content type from an array" do
|
|
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
|
|
|
128
|
-
describe
|
|
129
|
-
it
|
|
132
|
+
describe "#like?" do
|
|
133
|
+
it "compares two MIME::Types on #simplified values without x- prefixes" do
|
|
130
134
|
assert text_plain.like?(text_plain)
|
|
131
135
|
refute text_plain.like?(text_html)
|
|
132
136
|
end
|
|
133
137
|
|
|
134
|
-
it
|
|
138
|
+
it "compares MIME::Type against string without x- prefixes" do
|
|
135
139
|
assert text_plain.like?(text_plain.to_s)
|
|
136
140
|
refute text_plain.like?(text_html.to_s)
|
|
137
141
|
end
|
|
138
142
|
end
|
|
139
143
|
|
|
140
|
-
describe
|
|
141
|
-
it
|
|
144
|
+
describe "#<=>" do
|
|
145
|
+
it "correctly compares identical types" do
|
|
142
146
|
assert_equal text_plain, text_plain
|
|
143
147
|
end
|
|
144
148
|
|
|
145
|
-
it
|
|
146
|
-
right = mime_type(
|
|
149
|
+
it "correctly compares equivalent types" do
|
|
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
|
|
150
154
|
|
|
151
|
-
it
|
|
155
|
+
it "correctly compares types that sort earlier" do
|
|
152
156
|
refute_equal text_html, text_plain
|
|
153
157
|
assert_operator text_html, :<, text_plain
|
|
154
158
|
end
|
|
155
159
|
|
|
156
|
-
it
|
|
160
|
+
it "correctly compares types that sort later" do
|
|
157
161
|
refute_equal text_plain, text_html
|
|
158
162
|
assert_operator text_plain, :>, text_html
|
|
159
163
|
end
|
|
160
164
|
|
|
161
|
-
it
|
|
162
|
-
assert_equal text_plain,
|
|
165
|
+
it "correctly compares types against equivalent strings" do
|
|
166
|
+
assert_equal text_plain, "text/plain"
|
|
163
167
|
end
|
|
164
168
|
|
|
165
|
-
it
|
|
166
|
-
refute_equal text_html,
|
|
167
|
-
assert_operator text_html, :<,
|
|
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"
|
|
168
172
|
end
|
|
169
173
|
|
|
170
|
-
it
|
|
171
|
-
refute_equal text_plain,
|
|
172
|
-
assert_operator text_plain, :>,
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
it 'correctly compares against nil' do
|
|
176
|
-
refute_equal text_html, nil
|
|
177
|
-
assert_operator text_plain, :<, nil
|
|
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"
|
|
178
177
|
end
|
|
179
178
|
end
|
|
180
179
|
|
|
181
|
-
describe
|
|
182
|
-
it
|
|
180
|
+
describe "#ascii?" do
|
|
181
|
+
it "defaults to true for text/* types" do
|
|
183
182
|
assert text_plain.ascii?
|
|
184
183
|
end
|
|
185
184
|
|
|
186
|
-
it
|
|
185
|
+
it "defaults to false for non-text/* types" do
|
|
187
186
|
refute image_jpeg.ascii?
|
|
188
187
|
end
|
|
189
188
|
end
|
|
190
189
|
|
|
191
|
-
describe
|
|
192
|
-
it
|
|
190
|
+
describe "#binary?" do
|
|
191
|
+
it "defaults to false for text/* types" do
|
|
193
192
|
refute text_plain.binary?
|
|
194
193
|
end
|
|
195
194
|
|
|
196
|
-
it
|
|
195
|
+
it "defaults to true for non-text/* types" do
|
|
197
196
|
assert image_jpeg.binary?
|
|
198
197
|
end
|
|
199
198
|
end
|
|
200
199
|
|
|
201
|
-
describe
|
|
202
|
-
it
|
|
200
|
+
describe "#complete?" do
|
|
201
|
+
it "is true when there are extensions" do
|
|
203
202
|
assert text_x_yaml.complete?
|
|
204
203
|
end
|
|
205
204
|
|
|
206
|
-
it
|
|
207
|
-
refute mime_type(
|
|
205
|
+
it "is false when there are no extensions" do
|
|
206
|
+
refute mime_type("content-type" => "text/plain").complete?
|
|
208
207
|
end
|
|
209
208
|
end
|
|
210
209
|
|
|
211
|
-
describe
|
|
212
|
-
it
|
|
213
|
-
assert_equal
|
|
214
|
-
assert_equal
|
|
210
|
+
describe "#content_type" do
|
|
211
|
+
it "preserves the original case" do
|
|
212
|
+
assert_equal "text/plain", text_plain.content_type
|
|
213
|
+
assert_equal "text/vCard", mime_type("content-type" => "text/vCard").content_type
|
|
215
214
|
end
|
|
216
215
|
|
|
217
|
-
it
|
|
218
|
-
assert_equal
|
|
216
|
+
it "does not remove x- prefixes" do
|
|
217
|
+
assert_equal "x-appl/x-zip", x_appl_x_zip.content_type
|
|
219
218
|
end
|
|
220
219
|
end
|
|
221
220
|
|
|
222
|
-
describe
|
|
223
|
-
it
|
|
224
|
-
assert_equal
|
|
221
|
+
describe "#default_encoding" do
|
|
222
|
+
it "is quoted-printable for text/* types" do
|
|
223
|
+
assert_equal "quoted-printable", text_plain.default_encoding
|
|
225
224
|
end
|
|
226
225
|
|
|
227
|
-
it
|
|
228
|
-
assert_equal
|
|
226
|
+
it "is base64 for non-text/* types" do
|
|
227
|
+
assert_equal "base64", image_jpeg.default_encoding
|
|
229
228
|
end
|
|
230
229
|
end
|
|
231
230
|
|
|
232
|
-
describe
|
|
233
|
-
it
|
|
234
|
-
assert_equal
|
|
235
|
-
assert_equal
|
|
231
|
+
describe "#encoding, #encoding=" do
|
|
232
|
+
it "returns #default_encoding if not set explicitly" do
|
|
233
|
+
assert_equal "quoted-printable", text_plain.encoding
|
|
234
|
+
assert_equal "base64", image_jpeg.encoding
|
|
236
235
|
end
|
|
237
236
|
|
|
238
|
-
it
|
|
239
|
-
text_plain.encoding =
|
|
240
|
-
assert_equal
|
|
237
|
+
it "returns the set value when set" do
|
|
238
|
+
text_plain.encoding = "8bit"
|
|
239
|
+
assert_equal "8bit", text_plain.encoding
|
|
241
240
|
end
|
|
242
241
|
|
|
243
|
-
it
|
|
244
|
-
text_plain.encoding =
|
|
242
|
+
it "resets to the default encoding when set to nil or :default" do
|
|
243
|
+
text_plain.encoding = "8bit"
|
|
245
244
|
text_plain.encoding = nil
|
|
246
245
|
assert_equal text_plain.default_encoding, text_plain.encoding
|
|
247
246
|
text_plain.encoding = :default
|
|
248
247
|
assert_equal text_plain.default_encoding, text_plain.encoding
|
|
249
248
|
end
|
|
250
249
|
|
|
251
|
-
it
|
|
250
|
+
it "raises a MIME::Type::InvalidEncoding for an invalid encoding" do
|
|
252
251
|
exception = assert_raises MIME::Type::InvalidEncoding do
|
|
253
|
-
text_plain.encoding =
|
|
252
|
+
text_plain.encoding = "binary"
|
|
254
253
|
end
|
|
255
254
|
assert_equal 'Invalid Encoding "binary"', exception.to_s
|
|
256
255
|
end
|
|
257
256
|
end
|
|
258
257
|
|
|
259
|
-
describe
|
|
260
|
-
it
|
|
261
|
-
refute text_plain.eql?(
|
|
258
|
+
describe "#eql?" do
|
|
259
|
+
it "is not true for a non-MIME::Type" do
|
|
260
|
+
refute text_plain.eql?("text/plain")
|
|
262
261
|
end
|
|
263
262
|
|
|
264
|
-
it
|
|
263
|
+
it "is not true for a different MIME::Type" do
|
|
265
264
|
refute text_plain.eql?(image_jpeg)
|
|
266
265
|
end
|
|
267
266
|
|
|
268
|
-
it
|
|
269
|
-
assert text_plain
|
|
267
|
+
it "is true for an equivalent MIME::Type" do
|
|
268
|
+
assert text_plain.eql?(mime_type("content-type" => "text/Plain"))
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
it "is true for an equivalent subclass of MIME::Type" do
|
|
272
|
+
subclass = Class.new(MIME::Type)
|
|
273
|
+
assert text_plain.eql?(subclass.new("content-type" => "text/plain"))
|
|
270
274
|
end
|
|
271
275
|
end
|
|
272
276
|
|
|
273
|
-
describe
|
|
274
|
-
it
|
|
275
|
-
assert_equal
|
|
276
|
-
assert_equal %w(zip zp), x_appl_x_zip.extensions
|
|
277
|
+
describe "#hash" do
|
|
278
|
+
it "is the same between #eql? MIME::Type instances" do
|
|
279
|
+
assert_equal text_plain.hash, mime_type("content-type" => "text/plain").hash
|
|
277
280
|
end
|
|
278
281
|
|
|
279
|
-
it
|
|
280
|
-
|
|
281
|
-
assert_equal
|
|
282
|
+
it "is the same between #eql? MIME::Type instances of different classes" do
|
|
283
|
+
subclass = Class.new(MIME::Type)
|
|
284
|
+
assert_equal text_plain.hash, subclass.new("content-type" => "text/plain").hash
|
|
282
285
|
end
|
|
283
286
|
|
|
284
|
-
it
|
|
285
|
-
|
|
286
|
-
assert_equal %w(yaml), text_x_yaml.extensions
|
|
287
|
+
it "uses the #simplified value" do
|
|
288
|
+
assert_equal text_plain.hash, mime_type("content-type" => "text/Plain").hash
|
|
287
289
|
end
|
|
288
290
|
end
|
|
289
291
|
|
|
290
|
-
describe
|
|
291
|
-
it
|
|
292
|
+
describe "#extensions, #extensions=" do
|
|
293
|
+
it "returns an array of extensions" do
|
|
294
|
+
assert_equal %w[yaml yml], text_x_yaml.extensions
|
|
295
|
+
assert_equal %w[zip zp], x_appl_x_zip.extensions
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
it "sets a single extension when provided a single value" do
|
|
299
|
+
text_x_yaml.extensions = "yaml"
|
|
300
|
+
assert_equal %w[yaml], text_x_yaml.extensions
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
it "deduplicates extensions" do
|
|
304
|
+
text_x_yaml.extensions = %w[yaml yaml]
|
|
305
|
+
assert_equal %w[yaml], text_x_yaml.extensions
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
describe "#add_extensions" do
|
|
310
|
+
it "does not modify extensions when provided nil" do
|
|
292
311
|
text_x_yaml.add_extensions(nil)
|
|
293
|
-
assert_equal %w
|
|
312
|
+
assert_equal %w[yaml yml], text_x_yaml.extensions
|
|
294
313
|
end
|
|
295
314
|
|
|
296
|
-
it
|
|
297
|
-
text_x_yaml.add_extensions(
|
|
298
|
-
assert_equal %w
|
|
299
|
-
text_x_yaml.add_extensions(%w
|
|
300
|
-
assert_equal %w
|
|
315
|
+
it "remains deduplicated with duplicate values" do
|
|
316
|
+
text_x_yaml.add_extensions("yaml")
|
|
317
|
+
assert_equal %w[yaml yml], text_x_yaml.extensions
|
|
318
|
+
text_x_yaml.add_extensions(%w[yaml yz])
|
|
319
|
+
assert_equal %w[yaml yml yz], text_x_yaml.extensions
|
|
301
320
|
end
|
|
302
321
|
end
|
|
303
322
|
|
|
304
|
-
describe
|
|
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
|
+
|
|
305
334
|
def assert_priority_less(left, right)
|
|
306
|
-
assert_equal(-1, left.priority_compare(right))
|
|
335
|
+
assert_equal(-1, left.priority_compare(right), "#{priority(left)} is not less than #{priority(right)}")
|
|
307
336
|
end
|
|
308
337
|
|
|
309
338
|
def assert_priority_same(left, right)
|
|
310
|
-
assert_equal 0, left.priority_compare(right)
|
|
339
|
+
assert_equal 0, left.priority_compare(right), "#{priority(left)} is not equal to #{priority(right)}"
|
|
311
340
|
end
|
|
312
341
|
|
|
313
342
|
def assert_priority_more(left, right)
|
|
314
|
-
assert_equal 1, left.priority_compare(right)
|
|
343
|
+
assert_equal 1, left.priority_compare(right), "#{priority(left)} is not more than #{priority(right)}"
|
|
315
344
|
end
|
|
316
345
|
|
|
317
346
|
def assert_priority(left, middle, right)
|
|
318
347
|
assert_priority_less left, right
|
|
319
348
|
assert_priority_same left, middle
|
|
320
|
-
assert_priority_more right,
|
|
349
|
+
assert_priority_more right, middle
|
|
321
350
|
end
|
|
322
351
|
|
|
323
|
-
let(:text_1) { mime_type(
|
|
324
|
-
let(:text_1p) { mime_type(
|
|
325
|
-
let(:text_2) { mime_type(
|
|
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") }
|
|
326
355
|
|
|
327
|
-
it
|
|
356
|
+
it "sorts based on the simplified type when the sort priorities are the same" do
|
|
328
357
|
assert_priority text_1, text_1p, text_2
|
|
329
358
|
end
|
|
330
359
|
|
|
331
|
-
it
|
|
332
|
-
text_1.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
assert_priority_same text_1, text_2
|
|
336
|
-
|
|
337
|
-
text_2.registered = true
|
|
338
|
-
|
|
339
|
-
assert_priority_more text_1, text_2
|
|
340
|
-
end
|
|
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 }
|
|
341
363
|
|
|
342
|
-
|
|
343
|
-
text_1.registered = text_1p.registered = true
|
|
344
|
-
text_1b = mime_type(text_1) { |t| t.registered = false }
|
|
364
|
+
assert_priority_less text_1, text_1b
|
|
345
365
|
|
|
346
366
|
assert_priority text_1, text_1p, text_1b
|
|
347
367
|
end
|
|
348
368
|
|
|
349
|
-
it
|
|
350
|
-
text_1.
|
|
351
|
-
text_1b = mime_type(text_1) { |t| t.
|
|
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 }
|
|
352
372
|
|
|
353
373
|
assert_priority text_1, text_1p, text_1b
|
|
354
374
|
end
|
|
355
375
|
|
|
356
|
-
it
|
|
357
|
-
text_1.
|
|
358
|
-
text_1b = mime_type(text_1) { |t| t.
|
|
376
|
+
it "sorts (3) based on the registration state" do
|
|
377
|
+
text_1.registered = text_1p.registered = true
|
|
378
|
+
text_1b = mime_type(text_1) { |t| t.registered = false }
|
|
359
379
|
|
|
360
380
|
assert_priority text_1, text_1p, text_1b
|
|
361
381
|
end
|
|
362
382
|
|
|
363
|
-
it
|
|
364
|
-
text_1.
|
|
365
|
-
|
|
366
|
-
text_1b = mime_type(text_1) { |t| t.use_instead = nil }
|
|
383
|
+
it "sorts (4) based on the completeness" do
|
|
384
|
+
text_1.extensions = text_1p.extensions = "1"
|
|
385
|
+
text_1b = mime_type(text_1) { |t| t.extensions = nil }
|
|
367
386
|
|
|
368
387
|
assert_priority text_1, text_1p, text_1b
|
|
388
|
+
end
|
|
369
389
|
|
|
370
|
-
|
|
390
|
+
it "sorts based on extensions (more extensions sort lower)" do
|
|
391
|
+
text_1.extensions = ["foo", "bar"]
|
|
392
|
+
text_2.extensions = ["foo"]
|
|
371
393
|
|
|
372
|
-
|
|
394
|
+
assert_priority_less text_1, text_2
|
|
373
395
|
end
|
|
374
396
|
end
|
|
375
397
|
|
|
376
|
-
describe
|
|
377
|
-
it
|
|
378
|
-
assert_equal
|
|
398
|
+
describe "#raw_media_type" do
|
|
399
|
+
it "extracts the media type as case-preserved" do
|
|
400
|
+
assert_equal "Text", mime_type("content-type" => "Text/plain").raw_media_type
|
|
379
401
|
end
|
|
380
402
|
|
|
381
|
-
it
|
|
382
|
-
assert_equal(
|
|
403
|
+
it "does not remove x- prefixes" do
|
|
404
|
+
assert_equal("x-appl", x_appl_x_zip.raw_media_type)
|
|
383
405
|
end
|
|
384
406
|
end
|
|
385
407
|
|
|
386
|
-
describe
|
|
387
|
-
it
|
|
388
|
-
assert_equal
|
|
408
|
+
describe "#media_type" do
|
|
409
|
+
it "extracts the media type as lowercase" do
|
|
410
|
+
assert_equal "text", text_plain.media_type
|
|
389
411
|
end
|
|
390
412
|
|
|
391
|
-
it
|
|
392
|
-
assert_equal(
|
|
413
|
+
it "does not remove x- prefixes" do
|
|
414
|
+
assert_equal("x-appl", x_appl_x_zip.media_type)
|
|
393
415
|
end
|
|
394
416
|
end
|
|
395
417
|
|
|
396
|
-
describe
|
|
397
|
-
it
|
|
398
|
-
assert_equal
|
|
418
|
+
describe "#raw_media_type" do
|
|
419
|
+
it "extracts the media type as case-preserved" do
|
|
420
|
+
assert_equal "Text", mime_type("content-type" => "Text/plain").raw_media_type
|
|
399
421
|
end
|
|
400
422
|
|
|
401
|
-
it
|
|
402
|
-
assert_equal(
|
|
423
|
+
it "does not remove x- prefixes" do
|
|
424
|
+
assert_equal("x-appl", x_appl_x_zip.raw_media_type)
|
|
403
425
|
end
|
|
404
426
|
end
|
|
405
427
|
|
|
406
|
-
describe
|
|
407
|
-
it
|
|
408
|
-
assert_equal
|
|
428
|
+
describe "#sub_type" do
|
|
429
|
+
it "extracts the sub type as lowercase" do
|
|
430
|
+
assert_equal "plain", text_plain.sub_type
|
|
409
431
|
end
|
|
410
432
|
|
|
411
|
-
it
|
|
412
|
-
assert_equal(
|
|
433
|
+
it "does not remove x- prefixes" do
|
|
434
|
+
assert_equal("x-zip", x_appl_x_zip.sub_type)
|
|
413
435
|
end
|
|
414
436
|
end
|
|
415
437
|
|
|
416
|
-
describe
|
|
417
|
-
it
|
|
418
|
-
assert_equal
|
|
438
|
+
describe "#raw_sub_type" do
|
|
439
|
+
it "extracts the sub type as case-preserved" do
|
|
440
|
+
assert_equal "Plain", mime_type("content-type" => "text/Plain").raw_sub_type
|
|
419
441
|
end
|
|
420
442
|
|
|
421
|
-
it
|
|
422
|
-
assert_equal(
|
|
443
|
+
it "does not remove x- prefixes" do
|
|
444
|
+
assert_equal("x-zip", x_appl_x_zip.raw_sub_type)
|
|
423
445
|
end
|
|
424
446
|
end
|
|
425
447
|
|
|
426
|
-
describe
|
|
427
|
-
let(:t) { mime_type(
|
|
448
|
+
describe "#to_h" do
|
|
449
|
+
let(:t) { mime_type("content-type" => "a/b") }
|
|
450
|
+
|
|
451
|
+
def assert_has_keys(wanted_keys, actual, msg = nil)
|
|
452
|
+
wanted_keys = Array(wanted_keys).uniq.sort
|
|
453
|
+
actual_keys = if actual.is_a?(Hash)
|
|
454
|
+
actual.keys
|
|
455
|
+
else
|
|
456
|
+
actual.to_h.keys
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
missing = wanted_keys - actual_keys
|
|
460
|
+
pretty_wanted_keys = (wanted_keys + actual_keys).uniq.sort
|
|
461
|
+
|
|
462
|
+
msg = message(msg) {
|
|
463
|
+
"#{mu_pp(actual)} is missing attribute values\n#{diff(pretty_wanted_keys, actual_keys)}"
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
assert missing.empty?, msg
|
|
467
|
+
end
|
|
428
468
|
|
|
429
|
-
it
|
|
430
|
-
assert_has_keys
|
|
469
|
+
it "has the required keys (content-type, registered, encoding)" do
|
|
470
|
+
assert_has_keys %w[content-type registered encoding], t
|
|
431
471
|
end
|
|
432
472
|
|
|
433
|
-
it
|
|
434
|
-
assert_has_keys mime_type(t) { |v| v.docs =
|
|
473
|
+
it "has the docs key if there are documents" do
|
|
474
|
+
assert_has_keys "docs", mime_type(t) { |v| v.docs = "a" }
|
|
435
475
|
end
|
|
436
476
|
|
|
437
|
-
it
|
|
438
|
-
assert_has_keys mime_type(t) { |v| v.extensions =
|
|
439
|
-
'extensions'
|
|
477
|
+
it "has the extensions key if set" do
|
|
478
|
+
assert_has_keys "extensions", mime_type(t) { |v| v.extensions = "a" }
|
|
440
479
|
end
|
|
441
480
|
|
|
442
|
-
it
|
|
443
|
-
assert_has_keys mime_type(t) { |v| v.preferred_extension =
|
|
444
|
-
'preferred-extension'
|
|
481
|
+
it "has the preferred-extension key if set" do
|
|
482
|
+
assert_has_keys "preferred-extension", mime_type(t) { |v| v.preferred_extension = "a" }
|
|
445
483
|
end
|
|
446
484
|
|
|
447
|
-
it
|
|
448
|
-
assert_has_keys mime_type(t) { |v| v.obsolete = true }
|
|
485
|
+
it "has the obsolete key if set" do
|
|
486
|
+
assert_has_keys "obsolete", mime_type(t) { |v| v.obsolete = true }
|
|
449
487
|
end
|
|
450
488
|
|
|
451
|
-
it
|
|
452
|
-
assert_has_keys mime_type(t) { |v|
|
|
489
|
+
it "has the obsolete and use-instead keys if set" do
|
|
490
|
+
assert_has_keys %w[obsolete use-instead], mime_type(t) { |v|
|
|
453
491
|
v.obsolete = true
|
|
454
|
-
v.use_instead =
|
|
455
|
-
}
|
|
492
|
+
v.use_instead = "c/d"
|
|
493
|
+
}
|
|
456
494
|
end
|
|
457
495
|
|
|
458
|
-
it
|
|
459
|
-
assert_has_keys mime_type(t) { |v| v.signature = true }
|
|
496
|
+
it "has the signature key if set" do
|
|
497
|
+
assert_has_keys "signature", mime_type(t) { |v| v.signature = true }
|
|
460
498
|
end
|
|
461
499
|
end
|
|
462
500
|
|
|
463
|
-
describe
|
|
464
|
-
let(:
|
|
465
|
-
'{"content-type":"a/b","encoding":"base64","registered":false}'
|
|
501
|
+
describe "#to_json" do
|
|
502
|
+
let(:expected_1) {
|
|
503
|
+
'{"content-type":"a/b","encoding":"base64","registered":false,"sort-priority":48}'
|
|
504
|
+
}
|
|
505
|
+
let(:expected_2) {
|
|
506
|
+
'{"content-type":"a/b","encoding":"base64","registered":true,"provisional":true,"sort-priority":80}'
|
|
466
507
|
}
|
|
467
508
|
|
|
468
|
-
it
|
|
469
|
-
assert_equal
|
|
509
|
+
it "converts to JSON when requested" do
|
|
510
|
+
assert_equal expected_1, mime_type("content-type" => "a/b").to_json
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
it "converts to JSON with provisional when requested" do
|
|
514
|
+
type = mime_type("content-type" => "a/b") do |t|
|
|
515
|
+
t.registered = true
|
|
516
|
+
t.provisional = true
|
|
517
|
+
end
|
|
518
|
+
assert_equal expected_2, type.to_json
|
|
470
519
|
end
|
|
471
520
|
end
|
|
472
521
|
|
|
473
|
-
describe
|
|
474
|
-
it
|
|
475
|
-
assert_equal
|
|
522
|
+
describe "#to_s, #to_str" do
|
|
523
|
+
it "represents itself as a string of the canonical content_type" do
|
|
524
|
+
assert_equal "text/plain", text_plain.to_s
|
|
476
525
|
end
|
|
477
526
|
|
|
478
|
-
it
|
|
479
|
-
assert_equal text_plain,
|
|
527
|
+
it "acts like a string of the canonical content_type for comparison" do
|
|
528
|
+
assert_equal text_plain, "text/plain"
|
|
480
529
|
end
|
|
481
530
|
|
|
482
|
-
it
|
|
483
|
-
assert_equal
|
|
531
|
+
it "acts like a string for other purposes" do
|
|
532
|
+
assert_equal "stringy", "text/plain".sub(text_plain, "stringy")
|
|
484
533
|
end
|
|
485
534
|
end
|
|
486
535
|
|
|
487
|
-
describe
|
|
536
|
+
describe "#xrefs, #xrefs=" do
|
|
488
537
|
let(:expected) {
|
|
489
|
-
MIME::Types::Container.new(
|
|
538
|
+
MIME::Types::Container.new("rfc" => Set["rfc1234", "rfc5678"])
|
|
490
539
|
}
|
|
491
540
|
|
|
492
|
-
it
|
|
541
|
+
it "returns the expected results" do
|
|
493
542
|
application_javascript.xrefs = {
|
|
494
|
-
|
|
543
|
+
"rfc" => %w[rfc5678 rfc1234 rfc1234]
|
|
495
544
|
}
|
|
496
545
|
|
|
497
546
|
assert_equal expected, application_javascript.xrefs
|
|
498
547
|
end
|
|
499
548
|
end
|
|
500
549
|
|
|
501
|
-
describe
|
|
550
|
+
describe "#xref_urls" do
|
|
502
551
|
let(:expected) {
|
|
503
552
|
[
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
553
|
+
"http://www.iana.org/go/draft1",
|
|
554
|
+
"http://www.iana.org/assignments/media-types/a/b",
|
|
555
|
+
"http://www.iana.org/assignments/media-types/media-types.xhtml#p-1",
|
|
556
|
+
"http://www.iana.org/go/rfc-1",
|
|
557
|
+
"http://www.rfc-editor.org/errata_search.php?eid=err-1",
|
|
558
|
+
"http://example.org",
|
|
559
|
+
"text"
|
|
511
560
|
]
|
|
512
561
|
}
|
|
513
562
|
|
|
514
563
|
let(:type) {
|
|
515
|
-
mime_type(
|
|
564
|
+
mime_type("content-type" => "a/b").tap do |t|
|
|
516
565
|
t.xrefs = {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
566
|
+
"draft" => ["RFC1"],
|
|
567
|
+
"template" => ["a/b"],
|
|
568
|
+
"person" => ["p-1"],
|
|
569
|
+
"rfc" => ["rfc-1"],
|
|
570
|
+
"rfc-errata" => ["err-1"],
|
|
571
|
+
"uri" => ["http://example.org"],
|
|
572
|
+
"text" => ["text"]
|
|
524
573
|
}
|
|
525
574
|
end
|
|
526
575
|
}
|
|
527
576
|
|
|
528
|
-
it
|
|
577
|
+
it "translates according to given rules" do
|
|
529
578
|
assert_equal expected, type.xref_urls
|
|
530
579
|
end
|
|
531
580
|
end
|
|
532
581
|
|
|
533
|
-
describe
|
|
534
|
-
it
|
|
582
|
+
describe "#use_instead" do
|
|
583
|
+
it "is nil unless the type is obsolete" do
|
|
535
584
|
assert_nil text_plain.use_instead
|
|
536
585
|
end
|
|
537
586
|
|
|
538
|
-
it
|
|
587
|
+
it "is nil if not set and the type is obsolete" do
|
|
539
588
|
text_plain.obsolete = true
|
|
540
589
|
assert_nil text_plain.use_instead
|
|
541
590
|
end
|
|
542
591
|
|
|
543
|
-
it
|
|
592
|
+
it "is a different type if set and the type is obsolete" do
|
|
544
593
|
text_plain.obsolete = true
|
|
545
|
-
text_plain.use_instead =
|
|
546
|
-
assert_equal
|
|
594
|
+
text_plain.use_instead = "text/html"
|
|
595
|
+
assert_equal "text/html", text_plain.use_instead
|
|
547
596
|
end
|
|
548
597
|
end
|
|
549
598
|
|
|
550
|
-
describe
|
|
551
|
-
it
|
|
599
|
+
describe "#preferred_extension, #preferred_extension=" do
|
|
600
|
+
it "is nil when not set and there are no extensions" do
|
|
552
601
|
assert_nil text_plain.preferred_extension
|
|
553
602
|
end
|
|
554
603
|
|
|
555
|
-
it
|
|
556
|
-
assert_equal
|
|
604
|
+
it "is the first extension when not set but there are extensions" do
|
|
605
|
+
assert_equal "yaml", text_x_yaml.preferred_extension
|
|
557
606
|
end
|
|
558
607
|
|
|
559
|
-
it
|
|
560
|
-
text_x_yaml.preferred_extension =
|
|
561
|
-
assert_equal
|
|
608
|
+
it "is the extension provided when set" do
|
|
609
|
+
text_x_yaml.preferred_extension = "yml"
|
|
610
|
+
assert_equal "yml", text_x_yaml.preferred_extension
|
|
562
611
|
end
|
|
563
612
|
|
|
564
|
-
it
|
|
565
|
-
text_x_yaml.preferred_extension =
|
|
566
|
-
assert_equal
|
|
567
|
-
assert_includes text_x_yaml.extensions,
|
|
613
|
+
it "is adds the preferred extension if it does not exist" do
|
|
614
|
+
text_x_yaml.preferred_extension = "yz"
|
|
615
|
+
assert_equal "yz", text_x_yaml.preferred_extension
|
|
616
|
+
assert_includes text_x_yaml.extensions, "yz"
|
|
568
617
|
end
|
|
569
618
|
end
|
|
570
619
|
|
|
571
|
-
describe
|
|
572
|
-
it
|
|
573
|
-
assert_equal
|
|
620
|
+
describe "#friendly" do
|
|
621
|
+
it "returns English by default" do
|
|
622
|
+
assert_equal "YAML Structured Document", text_x_yaml.friendly
|
|
574
623
|
end
|
|
575
624
|
|
|
576
|
-
it
|
|
577
|
-
assert_equal
|
|
578
|
-
assert_equal
|
|
625
|
+
it "returns English when requested" do
|
|
626
|
+
assert_equal "YAML Structured Document", text_x_yaml.friendly("en")
|
|
627
|
+
assert_equal "YAML Structured Document", text_x_yaml.friendly(:en)
|
|
579
628
|
end
|
|
580
629
|
|
|
581
|
-
it
|
|
582
|
-
assert_nil text_x_yaml.friendly(
|
|
630
|
+
it "returns nothing for an unknown language" do
|
|
631
|
+
assert_nil text_x_yaml.friendly("zz")
|
|
583
632
|
end
|
|
584
633
|
|
|
585
|
-
it
|
|
586
|
-
expected = {
|
|
587
|
-
assert_equal expected, text_plain.friendly([
|
|
588
|
-
expected.update(
|
|
634
|
+
it "merges new values from an array parameter" do
|
|
635
|
+
expected = {"en" => "Text files"}
|
|
636
|
+
assert_equal expected, text_plain.friendly(["en", "Text files"])
|
|
637
|
+
expected.update("fr" => "des fichiers texte")
|
|
589
638
|
assert_equal expected,
|
|
590
|
-
|
|
639
|
+
text_plain.friendly(["fr", "des fichiers texte"])
|
|
591
640
|
end
|
|
592
641
|
|
|
593
|
-
it
|
|
594
|
-
expected = {
|
|
642
|
+
it "merges new values from a hash parameter" do
|
|
643
|
+
expected = {"en" => "Text files"}
|
|
595
644
|
assert_equal expected, text_plain.friendly(expected)
|
|
596
|
-
french = {
|
|
645
|
+
french = {"fr" => "des fichiers texte"}
|
|
597
646
|
expected.update(french)
|
|
598
647
|
assert_equal expected, text_plain.friendly(french)
|
|
599
648
|
end
|
|
600
649
|
|
|
601
|
-
it
|
|
650
|
+
it "raises an ArgumentError if an unknown value is provided" do
|
|
602
651
|
exception = assert_raises ArgumentError do
|
|
603
652
|
text_plain.friendly(1)
|
|
604
653
|
end
|
|
605
654
|
|
|
606
|
-
assert_equal
|
|
607
|
-
|
|
655
|
+
assert_equal "Expected a language or translation set, not 1",
|
|
656
|
+
exception.message
|
|
608
657
|
end
|
|
609
658
|
end
|
|
610
659
|
end
|