はじめに
hkob の雑記録の第163回目は、multipart のテストがうまく行えなかったことを記載します。
FileUploadObject#single_file_upload
とりあえず single_file_upload を実装してみました。作成した FileUploadObject の @id とファイル名を file_upload_request に投げているだけです。
def single_file_upload nc = NotionRubyMapping::NotionCache.instance response = nc.file_upload_request @fname, @id return if response[:id] == @id && response[:status] == "uploaded" raise StandardError, "File upload failed: #{response}" end
Notioncache#file_upload_request
file_upload_request は file_upload_path で作成した path に Multipart の request を送るだけです。
# @param [String] fname # @param [String] id # @param [Hash] options # @return [Hash] def file_upload_request(fname, id, options = {}) multipart_request(file_upload_path(id), options, fname) end
file_upload_path のテスト
file_uploads_path のテストは簡単です。
describe "file_upload_path" do it { expect(nc.file_upload_path("ABC")).to eq "v1/file_uploads/ABC/send" } end
NotionCache#file_upload_path
実装は簡単ですね。
# @param [String] id # @return [String] def file_upload_path(id) "v1/file_uploads/#{id}/send" end
NotionCache#multipart_request
multipart_request は Faraday::Multipart を使った専用の request です。
# @param [String] path # @param [Hash] json # @param [String] fname # @return [Hash] response hash def multipart_request(path, json, fname) raise "Please call `NotionRubyMapping.configure' before using other methods" unless @notion_token sleep @wait json_part = Faraday::Multipart::ParamPart.new(json.to_json, "application/json") file_part = Faraday::Multipart::FilePart.new(fname, "application/octet-stream", File.basename(fname)) response = multipart_client.send(:post) do |request| request.headers["Authorization"] = "Bearer #{@notion_token}" request.headers["content-Type"] = "multipart/form-data" request.path = path request.body = {json: json_part, file: file_part} end p response.body if @debug response.body end
NotionCache#multipart_client
multipart_client は毎回使うわけではないので、オプショナルのインスタンス変数にしました。conn.request に :multipart が設定されている点が通常の @client と異なる点です。
def multipart_client @multipart_client ||= Faraday.new "https://api.notion.com" do |conn| conn.request :multipart conn.response :json, parser_options: {symbolize_names: true} conn.headers["Notion-Version"] = NotionRubyMapping::NOTION_VERSION end end
WebMock の設定
FileUploadObject のテストを色々と頑張ったのですが、body のチェックで文字列比較をするときに UTF-8 と ASCII-8BIT の混ざったものを取り扱った瞬間にエラーになってしまうようです。body の比較をスキップする設定などを色々と試しているのですが、今のところうまくいっていません。テストで時間をかけても仕方がないので、簡易実装で動作することを確認したら、アップロード部分だけ WebMock ではなく、メソッドの stub で逃げてしまうかもしれません。
1) FileUploadObject initialize with a small file creates a new FileUploadObject Failure/Error: response = multipart_client.send(:post) do |request| request.headers["Authorization"] = "Bearer #{@notion_token}" request.headers["content-Type"] = "multipart/form-data" request.path = path request.body = {json: json_part, file: file_part} end Encoding::CompatibilityError: incompatible character encodings: BINARY (ASCII-8BIT) and UTF-8
おわりに
今日は忙しくて全くコードに触れることができず、進捗がありませんでした。