Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

F2: Test Freefeed API wrapper #595

Merged
merged 7 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ gem "honeybadger", "~> 5.15", ">= 5.15.6"
gem "http", "~> 5.2"
gem "jsbundling-rails"
gem "memo_wise", "~> 1.9"
gem "mimemagic", "~> 0.4.3"
gem "ostruct", "~> 0.6.0"
gem "pg", "~> 1.5"
gem "propshaft"
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ GEM
marcel (1.0.4)
memo_wise (1.10.0)
method_source (1.1.0)
mimemagic (0.4.3)
nokogiri (~> 1)
rake
mini_mime (1.1.5)
minitest (5.25.1)
msgpack (1.7.3)
Expand Down Expand Up @@ -407,6 +410,7 @@ DEPENDENCIES
http (~> 5.2)
jsbundling-rails
memo_wise (~> 1.9)
mimemagic (~> 0.4.3)
ostruct (~> 0.6.0)
pg (~> 1.5)
propshaft
Expand Down
Binary file added spec/fixtures/files/image_1x1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
133 changes: 133 additions & 0 deletions spec/lib/freefeed/downloader_spec.rb
Original file line number Diff line number Diff line change
@@ -1 +1,134 @@
require "rails_helper"

RSpec.describe Freefeed::Downloader do
let(:url) { "https://example.com/image.jpg" }
let(:http_client) { HTTP }
let(:downloader) { described_class.new(url: url, http_client: http_client) }
let(:binary_content) { File.read("spec/fixtures/files/image_1x1.jpg", mode: "rb") }

describe "successful download" do
before do
stub_request(:get, url)
.to_return(
status: 200,
body: binary_content,
headers: {"Content-Type" => "image/jpeg"}
)
end

it "yields IO object and content type" do
expect { |b| downloader.call(&b) }
.to yield_with_args(instance_of(StringIO), "image/jpeg")
end

it "downloads file with correct content" do
downloader.call do |io, mime_type|
expect(mime_type).to eq("image/jpeg")
expect(io.read).to eq(binary_content)
end
end

it "rewinds IO object before yielding" do
downloader.call do |io, _mime_type|
expect(io.pos).to eq(0)
end
end

it "sets binary encoding for IO object" do
downloader.call do |io, _mime_type|
expect(io.external_encoding).to eq(Encoding::BINARY)
end
end
end

describe "missing content type" do
before do
stub_request(:get, url)
.to_return(
status: 200,
body: binary_content,
headers: {}
)
end

it "yields IO object and nil content type" do
downloader.call do |io, mime_type|
expect(mime_type).to be_nil
expect(io.read).to eq(binary_content)
end
end
end

describe "network failures" do
it "returns nil on connection error" do
stub_request(:get, url).to_raise(HTTP::ConnectionError)

expect { |b| downloader.call(&b) }.not_to yield_control
expect(downloader.call {}).to be_nil
end

it "returns nil on timeout error" do
stub_request(:get, url).to_raise(HTTP::TimeoutError)

expect { |b| downloader.call(&b) }.not_to yield_control
expect(downloader.call {}).to be_nil
end
end

describe "error status codes" do
[403, 404, 500].each do |status|
it "returns nil for status #{status}" do
stub_request(:get, url).to_return(status: status)

expect { |b| downloader.call(&b) }.not_to yield_control
expect(downloader.call {}).to be_nil
end
end
end

describe "content types" do
{
"image/png" => "image.png",
"application/pdf" => "document.pdf",
"text/plain" => "text.txt",
"application/octet-stream" => "binary.dat"
}.each do |mime_type, filename|
it "handles #{mime_type} content type" do
stub_request(:get, "https://example.com/#{filename}")
.to_return(
status: 200,
body: binary_content,
headers: {"Content-Type" => mime_type}
)

downloader = described_class.new(
url: "https://example.com/#{filename}",
http_client: http_client
)

downloader.call do |io, content_type|
expect(content_type).to eq(mime_type)
expect(io.read).to eq(binary_content)
end
end
end
end

describe "empty response" do
before do
stub_request(:get, url)
.to_return(
status: 200,
body: "",
headers: {"Content-Type" => "text/plain"}
)
end

it "handles empty response correctly" do
downloader.call do |io, mime_type|
expect(mime_type).to eq("text/plain")
expect(io.read).to eq("")
end
end
end
end
94 changes: 94 additions & 0 deletions spec/lib/freefeed/v1/attachments_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
require "rails_helper"

RSpec.describe Freefeed::V1::Attachments do
let(:client) { Freefeed::Client.new(token: "token", base_url: "https://example.com") }

describe "#create_attachment" do
let(:file_path) { file_fixture("image_1x1.jpg") }

it "uploads a file from path" do
stub_request(:post, "https://example.com/v1/attachments")
.with(
headers: {
"Authorization" => "Bearer token",
"User-Agent" => "feeder"
}
)
.to_return(status: 200, body: "{}")

response = client.create_attachment(file_path)

expect(response.status.code).to eq(200)
end

it "uploads a file with explicit content type" do
stub_request(:post, "https://example.com/v1/attachments")
.with(
headers: {
"Authorization" => "Bearer token",
"User-Agent" => "feeder"
}
)
.to_return(status: 200, body: "{}")

response = client.create_attachment(file_path, content_type: "image/png")

expect(response.status.code).to eq(200)
end

it "uploads from IO object" do
stub_request(:post, "https://example.com/v1/attachments")
.with(
headers: {
"Authorization" => "Bearer token",
"User-Agent" => "feeder"
}
)
.to_return(status: 200, body: "{}")

io = StringIO.new("fake image content")
response = client.create_attachment(io)

expect(response.status.code).to eq(200)
end
end

describe "#create_attachment_from" do
let(:remote_url) { "https://example.com/image.jpg" }
let(:attachment_response) do
{
"attachments" => {
"id" => "attachment-123"
}
}.to_json
end

it "creates attachment from remote URL" do
# Stub the remote image download
stub_request(:get, remote_url)
.to_return(
status: 200,
body: "fake image content",
headers: {"Content-Type" => "image/jpeg"}
)

# Stub the attachment creation
stub_request(:post, "https://example.com/v1/attachments")
.with(
headers: {
"Authorization" => "Bearer token",
"User-Agent" => "feeder"
}
)
.to_return(
status: 200,
body: attachment_response,
headers: {"Content-Type" => "application/json"}
)

result = client.create_attachment_from(url: remote_url)

expect(result).to eq("attachment-123")
end
end
end
68 changes: 68 additions & 0 deletions spec/lib/freefeed/v1/comments_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
require "rails_helper"

RSpec.describe Freefeed::V1::Comments do
let(:client) { Freefeed::Client.new(token: "token", base_url: "https://example.com") }

describe "#create_comment" do
it "creates a comment" do
stub_request(:post, "https://example.com/v1/comments")
.with(
body: {
body: "Comment text",
postId: "post-123"
}.to_json,
headers: {
"Authorization" => "Bearer token",
"Content-Type" => "application/json; charset=utf-8",
"User-Agent" => "feeder"
}
)
.to_return(status: 200, body: "{}")

response = client.create_comment(
body: "Comment text",
postId: "post-123"
)
expect(response.status.code).to eq(200)
end
end

describe "#update_comment" do
it "updates a comment" do
stub_request(:put, "https://example.com/v1/comments/comment-123")
.with(
body: {
body: "Updated comment text"
}.to_json,
headers: {
"Authorization" => "Bearer token",
"Content-Type" => "application/json; charset=utf-8",
"User-Agent" => "feeder"
}
)
.to_return(status: 200, body: "{}")

response = client.update_comment(
"comment-123",
body: "Updated comment text"
)
expect(response.status.code).to eq(200)
end
end

describe "#delete_comment" do
it "deletes a comment" do
stub_request(:delete, "https://example.com/v1/comments/comment-123")
.with(
headers: {
"Authorization" => "Bearer token",
"User-Agent" => "feeder"
}
)
.to_return(status: 200, body: "{}")

response = client.delete_comment("comment-123")
expect(response.status.code).to eq(200)
end
end
end
Loading
Loading