- Add extensive test coverage for Bluesky user profile URL matching - Test handle-based and DID-based profile URLs with various formats - Add edge cases and error condition tests for malformed URLs - Test user avatar icon path and model path generation - Verify fallback behavior for users without display names - Test priority logic for handle vs DID lookup - Add tests for special characters and very long handles - All 82 tests now pass successfully
457 lines
15 KiB
Ruby
457 lines
15 KiB
Ruby
# typed: false
|
|
require "rails_helper"
|
|
|
|
RSpec.describe Domain::PostsHelper, type: :helper do
|
|
LinkForSource = Domain::PostsHelper::LinkForSource
|
|
|
|
describe "#page_str" do
|
|
context "when page is greater than 1" do
|
|
it "returns page string" do
|
|
expect(helper.page_str(page: "2")).to eq("(page 2)")
|
|
end
|
|
end
|
|
|
|
context "when page is 1 or not specified" do
|
|
it "returns nil" do
|
|
expect(helper.page_str(page: "1")).to be_nil
|
|
expect(helper.page_str({})).to be_nil
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#link_for_source" do
|
|
it "returns nil for invalid URLs" do
|
|
expect(helper.link_for_source("invalid-url")).to be_nil
|
|
end
|
|
|
|
it "returns nil for URLs that don't match any source matchers" do
|
|
expect(helper.link_for_source("https://www.google.com/")).to be_nil
|
|
end
|
|
|
|
describe "FA link handling" do
|
|
it "returns nil for FA URLs that are not found" do
|
|
expect(
|
|
helper.link_for_source("https://www.furaffinity.net/view/123456/"),
|
|
).to be_nil
|
|
end
|
|
|
|
%w[
|
|
https://www.furaffinity.net/view/123/
|
|
https://www.furaffinity.net/view/123
|
|
furaffinity.net/view/123/
|
|
furaffinity.net/view/123
|
|
www.furaffinity.net/view/123/
|
|
www.furaffinity.net/view/123
|
|
Furaffinity.net/view/123/
|
|
Furaffinity.net/view/123
|
|
].each do |url|
|
|
it "returns a link to FA post for #{url}" do
|
|
post = create(:domain_post_fa_post, fa_id: "123", title: "Post Title")
|
|
expect(url).to eq_link_for_source(model: post, title: "Post Title")
|
|
end
|
|
end
|
|
|
|
%w[
|
|
https://www.furaffinity.net/user/artistone/
|
|
https://www.furaffinity.net/user/artistone
|
|
https://furaffinity.net/user/artistone/
|
|
https://furaffinity.net/user/artistone
|
|
Furaffinity.net/user/artistone
|
|
furaffinity.net/user/artistone
|
|
www.furaffinity.net/user/artistone
|
|
].each do |url|
|
|
it "returns a link to FA user for #{url}" do
|
|
user =
|
|
create(
|
|
:domain_user_fa_user,
|
|
url_name: "artistone",
|
|
name: "Artist One",
|
|
)
|
|
expect(url).to eq_link_for_source(model: user, title: "Artist One")
|
|
end
|
|
end
|
|
|
|
%w[
|
|
inkbunny.net/s/123456-p3-#pictop
|
|
inkbunny.net/s/123456-p3-#pictop/
|
|
www.inkbunny.net/s/123456-p3-#pictop/
|
|
www.inkbunny.net/s/123456-p3-#pictop
|
|
Inkbunny.net/s/123456-p3-#pictop
|
|
inkbunny.net/submissionview.php?id=123456
|
|
http://inkbunny.net/submissionview.php?id=123456
|
|
http://www.inkbunny.net/submissionview.php?id=123456
|
|
].each do |url|
|
|
it "returns a link to inkbunny post for #{url}" do
|
|
post =
|
|
create(
|
|
:domain_post_inkbunny_post,
|
|
ib_id: "123456",
|
|
title: "Post Title",
|
|
)
|
|
expect(url).to eq_link_for_source(model: post, title: "Post Title")
|
|
end
|
|
end
|
|
|
|
%w[
|
|
https://www.inkbunny.net/user/artistone/
|
|
https://www.inkbunny.net/user/artistone
|
|
https://inkbunny.net/user/artistone/
|
|
https://inkbunny.net/user/artistone
|
|
http://www.inkbunny.net/user/ArtistOne
|
|
www.inkbunny.net/user/ArtistOne
|
|
Inkbunny.net/user/artistone
|
|
inkbunny.net/user/artistone
|
|
inkbunny.net/user/artistone/
|
|
www.inkbunny.net/user/artistone
|
|
www.inkbunny.net/user/artistone/
|
|
].each do |url|
|
|
it "returns a link to inkbunny user for #{url}" do
|
|
user = create(:domain_user_inkbunny_user, name: "artistone")
|
|
# binding.pry
|
|
expect(url).to eq_link_for_source(model: user, title: "artistone")
|
|
end
|
|
end
|
|
|
|
it "has the right avatar url" do
|
|
user =
|
|
create(
|
|
:domain_user_fa_user,
|
|
url_name: "artistone",
|
|
name: "Artist One",
|
|
)
|
|
create(:domain_user_avatar, user:)
|
|
|
|
link_for_source =
|
|
helper.link_for_source("https://www.furaffinity.net/user/artistone/")
|
|
expect(link_for_source).to be_present
|
|
expect(link_for_source.icon_path).to eq(
|
|
helper.domain_user_avatar_img_src_path(
|
|
user.avatar,
|
|
thumb: "64-avatar",
|
|
),
|
|
)
|
|
end
|
|
|
|
it "has the right model path" do
|
|
create(:domain_post_fa_post, fa_id: "123456", title: "Post Title")
|
|
link_for_source =
|
|
helper.link_for_source("https://www.furaffinity.net/view/123456/")
|
|
expect(link_for_source).to be_present
|
|
expect(link_for_source.model_path).to eq("/posts/fa@123456")
|
|
end
|
|
end
|
|
|
|
describe "Bluesky link handling" do
|
|
it "returns nil for Bluesky URLs that are not found" do
|
|
expect(
|
|
helper.link_for_source(
|
|
"https://bsky.app/profile/user1.bsky.social/post/123456",
|
|
),
|
|
).to be_nil
|
|
end
|
|
|
|
%w[
|
|
https://bsky.app/profile/user1.bsky.social/post/123456
|
|
https://bsky.app/profile/user1.bsky.social/post/123456/
|
|
bsky.app/profile/user1.bsky.social/post/123456
|
|
bsky.app/profile/user1.bsky.social/post/123456/
|
|
Bsky.app/profile/user1.bsky.social/post/123456
|
|
Bsky.app/profile/user1.bsky.social/post/123456/
|
|
].each do |url|
|
|
it "returns a link to Bluesky post for #{url}" do
|
|
user = create(:domain_user_bluesky_user, handle: "user1.bsky.social")
|
|
post =
|
|
create(
|
|
:domain_post_bluesky_post,
|
|
creator: user,
|
|
rkey: "123456",
|
|
at_uri: "at://#{user.did}/app.bsky.feed.post/123456",
|
|
text: "Bluesky Post Title",
|
|
)
|
|
expect(url).to eq_link_for_source(
|
|
model: post,
|
|
title: "Bluesky Post Title",
|
|
)
|
|
end
|
|
end
|
|
|
|
%w[
|
|
https://bsky.app/profile/did:plc:1234567890/post/abcdef
|
|
https://bsky.app/profile/did:plc:1234567890/post/abcdef/
|
|
bsky.app/profile/did:plc:1234567890/post/abcdef
|
|
bsky.app/profile/did:plc:1234567890/post/abcdef/
|
|
Bsky.app/profile/did:plc:1234567890/post/abcdef
|
|
Bsky.app/profile/did:plc:1234567890/post/abcdef/
|
|
].each do |url|
|
|
it "returns a link to Bluesky post for DID-based URL #{url}" do
|
|
post =
|
|
create(
|
|
:domain_post_bluesky_post,
|
|
rkey: "abcdef",
|
|
at_uri: "at://did:plc:1234567890/app.bsky.feed.post/abcdef",
|
|
text: "DID Bluesky Post",
|
|
)
|
|
expect(url).to eq_link_for_source(
|
|
model: post,
|
|
title: "DID Bluesky Post",
|
|
)
|
|
end
|
|
end
|
|
|
|
it "has the right model path for Bluesky posts" do
|
|
user = create(:domain_user_bluesky_user, handle: "user1.bsky.social")
|
|
post =
|
|
create(
|
|
:domain_post_bluesky_post,
|
|
creator: user,
|
|
rkey: "123456",
|
|
at_uri: "at://#{user.did}/app.bsky.feed.post/123456",
|
|
text: "Bluesky Post Title",
|
|
)
|
|
link_for_source =
|
|
helper.link_for_source(
|
|
"https://bsky.app/profile/user1.bsky.social/post/123456",
|
|
)
|
|
expect(link_for_source).to be_present
|
|
expect(link_for_source.model_path).to eq("/posts/bsky@123456")
|
|
end
|
|
|
|
it "handles URLs with different case variations" do
|
|
user = create(:domain_user_bluesky_user, handle: "user1.bsky.social")
|
|
post =
|
|
create(
|
|
:domain_post_bluesky_post,
|
|
creator: user,
|
|
rkey: "123456",
|
|
at_uri: "at://#{user.did}/app.bsky.feed.post/123456",
|
|
text: "Case Test Post",
|
|
)
|
|
# Test that the method handles case variations in the host part
|
|
# but the handle part should match exactly as stored in the database
|
|
expect(
|
|
"BSKY.APP/profile/user1.bsky.social/post/123456",
|
|
).to eq_link_for_source(model: post, title: "Case Test Post")
|
|
end
|
|
|
|
describe "Bluesky user profile handling" do
|
|
it "returns nil for Bluesky user URLs that are not found" do
|
|
expect(
|
|
helper.link_for_source(
|
|
"https://bsky.app/profile/nonexistent.bsky.social",
|
|
),
|
|
).to be_nil
|
|
end
|
|
|
|
%w[
|
|
https://bsky.app/profile/artist1.bsky.social
|
|
https://bsky.app/profile/artist1.bsky.social/
|
|
bsky.app/profile/artist1.bsky.social
|
|
bsky.app/profile/artist1.bsky.social/
|
|
Bsky.app/profile/artist1.bsky.social
|
|
Bsky.app/profile/artist1.bsky.social/
|
|
].each do |url|
|
|
it "returns a link to Bluesky user for handle-based URL #{url}" do
|
|
user =
|
|
create(
|
|
:domain_user_bluesky_user,
|
|
handle: "artist1.bsky.social",
|
|
display_name: "Artist One",
|
|
)
|
|
expect(url).to eq_link_for_source(model: user, title: "Artist One")
|
|
end
|
|
end
|
|
|
|
%w[
|
|
https://bsky.app/profile/did:plc:1234567890abcdef
|
|
https://bsky.app/profile/did:plc:1234567890abcdef/
|
|
bsky.app/profile/did:plc:1234567890abcdef
|
|
bsky.app/profile/did:plc:1234567890abcdef/
|
|
Bsky.app/profile/did:plc:1234567890abcdef
|
|
Bsky.app/profile/did:plc:1234567890abcdef/
|
|
].each do |url|
|
|
it "returns a link to Bluesky user for DID-based URL #{url}" do
|
|
user =
|
|
create(
|
|
:domain_user_bluesky_user,
|
|
did: "did:plc:1234567890abcdef",
|
|
handle: "artist2.bsky.social",
|
|
display_name: "Artist Two",
|
|
)
|
|
expect(url).to eq_link_for_source(model: user, title: "Artist Two")
|
|
end
|
|
end
|
|
|
|
it "handles user with no display name, falling back to handle" do
|
|
user =
|
|
create(
|
|
:domain_user_bluesky_user,
|
|
handle: "user.bsky.social",
|
|
display_name: nil,
|
|
)
|
|
expect(
|
|
"https://bsky.app/profile/user.bsky.social",
|
|
).to eq_link_for_source(model: user, title: "@user.bsky.social")
|
|
end
|
|
|
|
it "has the right avatar icon path for Bluesky users" do
|
|
user =
|
|
create(
|
|
:domain_user_bluesky_user,
|
|
handle: "artist.bsky.social",
|
|
display_name: "Artist",
|
|
)
|
|
create(:domain_user_avatar, user: user)
|
|
|
|
link_for_source =
|
|
helper.link_for_source(
|
|
"https://bsky.app/profile/artist.bsky.social",
|
|
)
|
|
expect(link_for_source).to be_present
|
|
expect(link_for_source.icon_path).to eq(
|
|
helper.domain_user_avatar_img_src_path(
|
|
user.avatar,
|
|
thumb: "64-avatar",
|
|
),
|
|
)
|
|
end
|
|
|
|
it "has the right model path for Bluesky users" do
|
|
user =
|
|
create(
|
|
:domain_user_bluesky_user,
|
|
handle: "artist.bsky.social",
|
|
display_name: "Artist",
|
|
)
|
|
link_for_source =
|
|
helper.link_for_source(
|
|
"https://bsky.app/profile/artist.bsky.social",
|
|
)
|
|
expect(link_for_source).to be_present
|
|
expect(link_for_source.model_path).to match(%r{/users/bsky@[\w-]+})
|
|
end
|
|
|
|
it "handles case variations for user profiles" do
|
|
user =
|
|
create(
|
|
:domain_user_bluesky_user,
|
|
handle: "artist.bsky.social",
|
|
display_name: "Artist",
|
|
)
|
|
# Test that the method handles case variations in the host part
|
|
# but the handle part should match exactly as stored in the database
|
|
expect("BSKY.APP/profile/artist.bsky.social").to eq_link_for_source(
|
|
model: user,
|
|
title: "Artist",
|
|
)
|
|
end
|
|
|
|
it "prioritizes handle lookup over DID for user without DID prefix" do
|
|
# Create two users - one with handle that could be confused with DID format
|
|
user_with_handle =
|
|
create(
|
|
:domain_user_bluesky_user,
|
|
handle: "did.test.bsky.social",
|
|
display_name: "User with DID-like handle",
|
|
)
|
|
user_with_did =
|
|
create(
|
|
:domain_user_bluesky_user,
|
|
did: "did:plc:test123",
|
|
handle: "other.bsky.social",
|
|
display_name: "User with actual DID",
|
|
)
|
|
|
|
# Should match by handle first
|
|
expect(
|
|
"https://bsky.app/profile/did.test.bsky.social",
|
|
).to eq_link_for_source(
|
|
model: user_with_handle,
|
|
title: "User with DID-like handle",
|
|
)
|
|
end
|
|
|
|
it "matches DID-based URLs correctly when DID prefix is present" do
|
|
user =
|
|
create(
|
|
:domain_user_bluesky_user,
|
|
did: "did:plc:test123abc",
|
|
handle: "artist.bsky.social",
|
|
display_name: "DID Artist",
|
|
)
|
|
expect(
|
|
"https://bsky.app/profile/did:plc:test123abc",
|
|
).to eq_link_for_source(model: user, title: "DID Artist")
|
|
end
|
|
end
|
|
|
|
describe "edge cases and error conditions" do
|
|
it "returns nil for malformed DID in post URL" do
|
|
expect(
|
|
helper.link_for_source(
|
|
"https://bsky.app/profile/did:malformed/post/123",
|
|
),
|
|
).to be_nil
|
|
end
|
|
|
|
it "returns nil for malformed DID in user profile URL" do
|
|
expect(
|
|
helper.link_for_source("https://bsky.app/profile/did:malformed"),
|
|
).to be_nil
|
|
end
|
|
|
|
it "returns nil for empty handle in URL" do
|
|
expect(
|
|
helper.link_for_source("https://bsky.app/profile//post/123"),
|
|
).to be_nil
|
|
end
|
|
|
|
it "handles posts where user exists but post doesn't" do
|
|
user = create(:domain_user_bluesky_user, handle: "artist.bsky.social")
|
|
# No post created
|
|
expect(
|
|
helper.link_for_source(
|
|
"https://bsky.app/profile/artist.bsky.social/post/nonexistent",
|
|
),
|
|
).to be_nil
|
|
end
|
|
|
|
it "handles posts with DID where user doesn't exist" do
|
|
expect(
|
|
helper.link_for_source(
|
|
"https://bsky.app/profile/did:plc:nonexistent/post/123",
|
|
),
|
|
).to be_nil
|
|
end
|
|
|
|
it "handles very long handles correctly" do
|
|
long_handle = "a" * 100 + ".bsky.social"
|
|
user =
|
|
create(
|
|
:domain_user_bluesky_user,
|
|
handle: long_handle,
|
|
display_name: "Long Handle User",
|
|
)
|
|
|
|
expect(
|
|
"https://bsky.app/profile/#{long_handle}",
|
|
).to eq_link_for_source(model: user, title: "Long Handle User")
|
|
end
|
|
|
|
it "handles special characters in handles correctly" do
|
|
handle_with_specials = "test-user_123.bsky.social"
|
|
user =
|
|
create(
|
|
:domain_user_bluesky_user,
|
|
handle: handle_with_specials,
|
|
display_name: "Special User",
|
|
)
|
|
|
|
expect(
|
|
"https://bsky.app/profile/#{handle_with_specials}",
|
|
).to eq_link_for_source(model: user, title: "Special User")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|