1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
|
# frozen_string_literal: true
require "abstract_unit"
module TestFileUtils
def file_name() File.basename(__FILE__) end
def file_path() __FILE__ end
def file_data() @data ||= File.binread(file_path) end
end
class SendFileController < ActionController::Base
include TestFileUtils
include ActionController::Testing
layout "layouts/standard" # to make sure layouts don't interfere
before_action :file, only: :file_from_before_action
attr_writer :options
def options
@options ||= {}
end
def file
send_file(file_path, options)
end
def file_from_before_action
raise "No file sent from before action."
end
def test_send_file_headers_bang
options = {
type: Mime[:png],
disposition: "disposition",
filename: "filename"
}
send_data "foo", options
end
def test_send_file_headers_with_disposition_as_a_symbol
options = {
type: Mime[:png],
disposition: :disposition,
filename: "filename"
}
send_data "foo", options
end
def test_send_file_headers_with_mime_lookup_with_symbol
options = { type: :png }
send_data "foo", options
end
def test_send_file_headers_with_bad_symbol
options = { type: :this_type_is_not_registered }
send_data "foo", options
end
def test_send_file_headers_with_nil_content_type
options = { type: nil }
send_data "foo", options
end
def test_send_file_headers_guess_type_from_extension
options = { filename: params[:filename] }
send_data "foo", options
end
def data
send_data(file_data, options)
end
end
class SendFileWithActionControllerLive < SendFileController
include ActionController::Live
end
class SendFileTest < ActionController::TestCase
include TestFileUtils
def setup
@controller = SendFileController.new
end
def test_file_nostream
@controller.options = { stream: false }
response = nil
assert_nothing_raised { response = process("file") }
assert_not_nil response
body = response.body
assert_kind_of String, body
assert_equal file_data, body
end
def test_file_stream
response = nil
assert_nothing_raised { response = process("file") }
assert_not_nil response
assert_respond_to response.stream, :each
assert_respond_to response.stream, :to_path
require "stringio"
output = StringIO.new
output.binmode
output.string.force_encoding(file_data.encoding)
response.body_parts.each { |part| output << part.to_s }
assert_equal file_data, output.string
end
def test_file_url_based_filename
@controller.options = { url_based_filename: true }
response = nil
assert_nothing_raised { response = process("file") }
assert_not_nil response
assert_equal "attachment", response.headers["Content-Disposition"]
end
def test_data
response = nil
assert_nothing_raised { response = process("data") }
assert_not_nil response
assert_kind_of String, response.body
assert_equal file_data, response.body
end
def test_headers_after_send_shouldnt_include_charset
response = process("data")
assert_equal "application/octet-stream", response.headers["Content-Type"]
response = process("file")
assert_equal "application/octet-stream", response.headers["Content-Type"]
end
# Test that send_file_headers! is setting the correct HTTP headers.
def test_send_file_headers_bang
# Do it a few times: the resulting headers should be identical
# no matter how many times you send with the same options.
# Test resolving Ticket #458.
5.times do
get :test_send_file_headers_bang
assert_equal "image/png", response.content_type
assert_equal %(disposition; filename="filename"; filename*=UTF-8''filename), response.get_header("Content-Disposition")
assert_equal "binary", response.get_header("Content-Transfer-Encoding")
end
end
def test_send_file_headers_with_disposition_as_a_symbol
get :test_send_file_headers_with_disposition_as_a_symbol
assert_equal %(disposition; filename="filename"; filename*=UTF-8''filename), response.get_header("Content-Disposition")
end
def test_send_file_headers_with_mime_lookup_with_symbol
get __method__
assert_equal "image/png", response.content_type
end
def test_send_file_headers_with_bad_symbol
error = assert_raise(ArgumentError) { get __method__ }
assert_equal "Unknown MIME type this_type_is_not_registered", error.message
end
def test_send_file_headers_with_nil_content_type
error = assert_raise(ArgumentError) { get __method__ }
assert_equal ":type option required", error.message
end
def test_send_file_headers_guess_type_from_extension
{
"image.png" => "image/png",
"image.jpeg" => "image/jpeg",
"image.jpg" => "image/jpeg",
"image.tif" => "image/tiff",
"image.gif" => "image/gif",
"movie.mp4" => "video/mp4",
"file.zip" => "application/zip",
"file.unk" => "application/octet-stream",
"zip" => "application/octet-stream"
}.each do |filename, expected_type|
get __method__, params: { filename: filename }
assert_equal expected_type, response.content_type
end
end
def test_send_file_with_default_content_disposition_header
process("data")
assert_equal "attachment", @controller.headers["Content-Disposition"]
end
def test_send_file_without_content_disposition_header
@controller.options = { disposition: nil }
process("data")
assert_nil @controller.headers["Content-Disposition"]
end
def test_send_file_from_before_action
response = nil
assert_nothing_raised { response = process("file_from_before_action") }
assert_not_nil response
assert_kind_of String, response.body
assert_equal file_data, response.body
end
def test_send_file_instrumentation
@controller.options = { disposition: :inline }
payload = nil
subscriber = proc do |event|
payload = event.payload
end
ActiveSupport::Notifications.subscribed(subscriber, "send_file.action_controller") do
process("file")
end
assert_equal __FILE__, payload[:path]
assert_equal :inline, payload[:disposition]
end
def test_send_data_instrumentation
@controller.options = { content_type: "application/x-ruby" }
payload = nil
subscriber = proc do |event|
payload = event.payload
end
ActiveSupport::Notifications.subscribed(subscriber, "send_data.action_controller") do
process("data")
end
assert_equal("application/x-ruby", payload[:content_type])
end
%w(file data).each do |method|
define_method "test_send_#{method}_status" do
@controller.options = { stream: false, status: 500 }
assert_not_nil process(method)
assert_equal 500, @response.status
end
define_method "test_send_#{method}_content_type" do
@controller.options = { stream: false, content_type: "application/x-ruby" }
assert_nothing_raised { assert_not_nil process(method) }
assert_equal "application/x-ruby", @response.content_type
end
define_method "test_default_send_#{method}_status" do
@controller.options = { stream: false }
assert_nothing_raised { assert_not_nil process(method) }
assert_equal 200, @response.status
end
end
def test_send_file_with_action_controller_live
@controller = SendFileWithActionControllerLive.new
@controller.options = { content_type: "application/x-ruby" }
response = process("file")
assert_equal 200, response.status
end
def test_send_file_charset_with_type_options_key
@controller = SendFileWithActionControllerLive.new
@controller.options = { type: "text/calendar; charset=utf-8" }
response = process("file")
assert_equal "text/calendar; charset=utf-8", response.headers["Content-Type"]
end
def test_send_file_charset_with_type_options_key_without_charset
@controller = SendFileWithActionControllerLive.new
@controller.options = { type: "image/png" }
response = process("file")
assert_equal "image/png", response.headers["Content-Type"]
end
def test_send_file_charset_with_content_type_options_key
@controller = SendFileWithActionControllerLive.new
@controller.options = { content_type: "text/calendar" }
response = process("file")
assert_equal "text/calendar", response.headers["Content-Type"]
end
end
|