はじめに
hkob の雑記録の第170回目は、ファイルブロックへの File Upload object の更新のテストを追加します。
update_block_file_file_upload
今日は FileBlock へ file_upload_object= メソッドをテスト・実装します。まずは、before で file_upload_object= を実行し、updata_block_json が正しいことを確認します。
describe "update_block_file_file_upload" do let(:target) { described_class.new "abc", id: "20bd8e4e-98ab-8081-ad29-dd62726e4525" } let(:file_upload_object) do instance_double FileUploadObject, id: TestConnection::FILE_UPLOAD_IMAGE_ID, fname: "test.png" end before do allow(file_upload_object).to receive(:is_a?).with(FileUploadObject).and_return(true) target.file_upload_object = file_upload_object end it { expect(target.update_block_json).to eq( { type => { file_upload: { id: file_upload_object.id, }, }, }, ) }
FileObject は type の設定以外は全て FileBaseBlock に丸投げです。
# frozen_string_literal: true module NotionRubyMapping # Notion block class FileBlock < FileBaseBlock # @return [Symbol] def type :file end end end
FileBaseBlock に file_upload_object= を実装します。
# @param [FileUploadObject] fuo def file_upload_object=(fuo) @file_object.file_upload_object = fuo @payload.add_update_block_key :file_upload end
これにより、テストが通過しました。
update_block_file_file_upload
is expected to eq {file: {file_upload: {id: "20cd8e4e98ab81aa973b00b23083c115"}}}
続いて、dry_run のテストを追加します。
context "when dry_run" do
let(:dry_run) { target.save dry_run: true }
it_behaves_like "dry run", :patch, :block_path, use_id: true, json_method: :update_block_json
end
こちらは問題なくテストが通過します。
when dry_run
behaves like dry run
is expected to eq "#!/bin/sh\ncurl -X PATCH 'https://api.notion.com/v1/blocks/20bd8e4e98ab8081ad29dd62726e4525' \\\n -...ion/json' \\\n --data '{\"file\":{\"file_upload\":{\"id\":\"20cd8e4e98ab81aa973b00b23083c115\"}}}'"
最後に実際の save のテストを記述します。
context "when save" do it { expect(target.save.url).to eq "https://prod-files-secure.s3.us-west-2.amazonaws.com/2b7b01f0-67a8-40f8-acd4-88dd2805f216/bf91dfb5-72e5-4c22-bab7-f4b9f343610f/ErSxuLeq.png-medium.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB4666A5RECQ7%2F20250608%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250608T115825Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjELD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCXVzLXdlc3QtMiJIMEYCIQD5ST8JlsjghfDkcWp3xihh%2B0byAjsIDkc2aW0IRkSS%2BAIhAMphaW6h2vfFunHO%2B1EGb6DlLiEJ4rreBcZiS47i4ZitKogECIn%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEQABoMNjM3NDIzMTgzODA1Igwk%2FzBEoNUbyockbjkq3ANZmgEJWqJ2HdqMUyNcpJtNI4gToQ%2BcAXYswsfyNcJvV1yDazhob0KYQ%2FpniSCQPa6iORJ53Wyheg5Fo0GPvXE60bUhtcY0VKGg8U1HXVEwpATztFO6R37eAhsN6t6eN4y5ndn6CRjxVwCi5hX%2Fvfs4i6pzUDIZXvmtlSJJLt4BXdadf%2BhXADgDfL2d2qLyzdnA%2BPR7R0a9RuCAhp7cnqFbBNVrVmtgk1XUNdobV81ij%2BY6%2B2Gwf1k8j9MhaWDO1LQiUzwDErCscM%2Bp0WjREbgnfu%2F1QiFrsoJ2%2FnBvVKmFY3fPkYfwwPWCqlyjPLUqBWVdlCbhTz9UqWun%2BpXUZ9qCvWI%2FPOz43FKBvBLnefqG5tkqbyDAVh5escZisLK%2FtmV5ptWm%2FZf2U2SUeCyh8cOGLvon3%2Bf2GSfRj0T2abrWtXRzOTFJYJiMRmtHrnwGZ%2BrJmiSjU%2F5NH27e6kny6IZSIZwgW%2Fppejlfclzp2Qp0C8KDSuNZaHtcm7D5bFxN1DNGASnyz6C9pYu8QVw4vKpQXgr6rEvVHV6YXZB3EOwWAHD4%2FuA6Fg6dWJxy6N02RUZ%2B1ofSWPAIP9K67hzOfB0IhHH65TkmQDzXNMQADpB140RqyFKGlzSzOsh7bjDggZXCBjqkARQOaKDzsXc5QS2OtVCc5oPeV%2BQ%2FIYfM2uLFQQRlb4MjSRalKjK2%2Flkyn5CMLRqnapi1KzGq5KllHIuKBP6OeO6EF0Xk%2B4Mjtt%2BiFm6tofYK4T7%2BcVSUdIAR5TOF6WPN7vhHAKbGm1tZu5gbzxyKuJk5SVrSVdeakBr1N2sQTzFoGOjOcCm%2B8mkWKD7PR0nCEGTL1QnHt%2BYAKBf9AFBEZ3kdiulS&X-Amz-Signature=a12e8df1da28ef5b129263f215ec13f839c89ac1bcf6e03ba4e707117a4cc66d&X-Amz-SignedHeaders=host&x-id=GetObject" } end end
save の方は WebMock の stub が存在しないので、以下のようなエラーになりました。
1) NotionRubyMapping::FileBlock update_block_file_file_upload when save Failure/Error: response = @client.send(method) do |request| request.headers["Authorization"] = "Bearer #{@notion_token}" case method when :get, :delete request.url path, options when :post, :put, :patch request.headers["Content-Type"] = "application/json" request.path = path request.body = options.to_json unless options.empty? else WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Please stub: PATCH https://api.notion.com/v1/blocks/20bd8e4e98ab8081ad29dd62726e4525 with body '{"file":{"file_upload":{"id":"20cd8e4e98ab81aa973b00b23083c115"}}}' with headers {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer secret_J08RBf9SlofiMhuIeJZc6AnI5qHXwDOaq4RolJFaaZ0', 'Content-Type'=>'application/json', 'Notion-Version'=>'2022-06-28', 'User-Agent'=>'Faraday v2.13.1'}
dry_run で送られる payload に対する stub が必要となります。これは spec_helper にて登録を行います。upload_block の下に stubs を一括作成するメソッドを用意しているので、そこに payload を追加します。FileBlock の id のページに、{} 以下の payload を入れた時に、200 の response code を返し、update_block_file_file_upload.json を返すという stub が追加されます。
def update_block generate_stubs_sub :patch, __method__, :block_path, { (中略) file_file_upload: [ "20bd8e4e98ab8081ad29dd62726e4525", 200, { file: { file_upload: { id: TestConnection::FILE_UPLOAD_IMAGE_ID, }, }, } ], } end
これで動作すると思ったのですが、FileUpload で送信されたブロックは、Response として内部ファイル URL として返却されてきます。その他のブロックは保存したデータをそのまま保持しておけばいいのですが、FileBlock に関してだけは、ページプロパティと同様に Response で更新する必要があるようです。
NameError: undefined local variable or method 'url' for #<RSpec::ExampleGroups::NotionRubyMappingFileBlock::UpdateBlockFileFileUpload::WhenSave:0x000000011e6326c0> # ./spec/notion_ruby_mapping/blocks/file_block_spec.rb:76:in 'block (4 levels) in <module:NotionRubyMapping>'
そこで、block.rb における update 時に FileBaseBlock の時だけ、file_object を更新する処理を記載しました。
# @param [Boolean] dry_run true if dry_run # @return [NotionRubyMapping::Base, String] def update(dry_run: false) if dry_run dry_run_script :patch, @nc.block_path(@id), :update_block_json else @json = @nc.update_block_request(@id, update_block_json) update_file_object_from_json(@json) if is_a? FileBaseBlock end end
update_file_object_from_json は親クラスである FileBaseBlock に実装しました。
def update_file_object_from_json(json) @file_object = FileObject.new json: json[type] decode_block_caption @can_append = @file_object.external? end
これによって、save も無事にテストが通過しました。
when save
is expected to eq "https://prod-files-secure.s3.us-west-2.amazonaws.com/2b7b01f0-67a8-40f8-acd4-88dd2805f216/bf91dfb5-7...df1da28ef5b129263f215ec13f839c89ac1bcf6e03ba4e707117a4cc66d&X-Amz-SignedHeaders=host&x-id=GetObject"
Finished in 0.09002 seconds (files took 0.35502 seconds to load)
16 examples, 0 failures
おわりに
FileBlock の更新処理も無事にテストが通過しました。明日は、ImageBlock の更新を実施します。こちらも FileBaseObject のサブクラスになっているので、テストを書くだけでよい気がします。