Files
volumen/test/server_test.rb
T

278 lines
7.9 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
require "test_helper"
require "volumen/server"
require "rack/test"
require "tmpdir"
require "fileutils"
require "json"
class ServerTest < Minitest::Test
include Rack::Test::Methods
def app
Volumen::Server.configured(config: @config, store: @store)
end
def setup
@dir = Dir.mktmpdir
File.write(File.join(@dir, "hello.md"), <<~POST)
+++
title = "Hello"
tags = ["intro"]
+++
Hello **world**.
POST
File.write(File.join(@dir, "draft.md"), <<~POST)
+++
title = "Draft"
draft = true
+++
Secret.
POST
@config = Volumen::Config.load(path: "/nonexistent", overrides: { content: @dir })
@store = Volumen::Store.new(@dir, default_lang: "en")
end
def teardown
FileUtils.remove_entry(@dir)
end
def test_site_endpoint
get "/api/volumen/site"
assert_predicate last_response, :ok?
assert_equal "My Blog", JSON.parse(last_response.body)["title"]
end
def test_posts_excludes_drafts
get "/api/volumen/posts"
data = JSON.parse(last_response.body)
assert_equal 1, data["total"]
assert_equal "hello", data["posts"].first["slug"]
end
def test_post_detail_renders_html
get "/api/volumen/posts/hello"
assert_predicate last_response, :ok?
assert_includes JSON.parse(last_response.body)["html"], "<strong>world</strong>"
end
def test_post_not_found
get "/api/volumen/posts/missing"
assert_equal 404, last_response.status
assert_equal "not_found", JSON.parse(last_response.body)["error"]
end
def test_tags_endpoint
get "/api/volumen/tags"
assert_equal [{ "name" => "intro", "count" => 1 }], JSON.parse(last_response.body)["tags"]
end
def test_cors_header_present
get "/api/volumen/site"
header = last_response.headers["Access-Control-Allow-Origin"] ||
last_response.headers["access-control-allow-origin"]
assert_equal "*", header
end
def test_all_langs_post_appears_in_other_languages
File.write(File.join(@dir, "global.md"), <<~POST)
+++
title = "Global"
lang = "en"
all_langs = true
+++
Everywhere.
POST
get "/api/volumen/posts?lang=cs"
slugs = JSON.parse(last_response.body)["posts"].map { |post| post["slug"] }
assert_includes slugs, "global"
refute_includes slugs, "hello"
end
2026-06-25 21:41:19 +02:00
def test_feed_endpoint
get "/api/volumen/feed.xml"
assert_predicate last_response, :ok?
assert_equal "application/rss+xml", last_response["Content-Type"]&.split(";")&.first
body = last_response.body
assert_includes body, "<rss version=\"2.0\""
2026-06-25 21:41:19 +02:00
assert_includes body, "<title>Hello</title>"
refute_includes body, "Draft"
assert_includes body, "<language>en</language>"
end
def test_draft_post_detail_is_not_found
get "/api/volumen/posts/draft"
assert_equal 404, last_response.status
assert_equal "not_found", JSON.parse(last_response.body)["error"]
end
2026-06-25 21:51:32 +02:00
def test_sitemap_endpoint
get "/api/volumen/sitemap.xml"
assert_predicate last_response, :ok?
assert_equal "application/xml", last_response["Content-Type"]&.split(";")&.first
body = last_response.body
assert_includes body, "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">"
assert_includes body, "<loc>https://example.com/hello</loc>"
refute_includes body, "draft"
end
def test_cors_preflight
options "/api/volumen/site"
assert_predicate last_response, :ok?
assert_equal "*", last_response.headers["Access-Control-Allow-Origin"]
assert_equal "GET, OPTIONS", last_response.headers["Access-Control-Allow-Methods"]
end
def test_scheduled_post_is_hidden
future = (Date.today + 30).strftime("%Y-%m-%d")
File.write(File.join(@dir, "later.md"), <<~POST)
+++
title = "Later"
publish_at = #{future}
+++
Not yet.
POST
get "/api/volumen/posts"
slugs = JSON.parse(last_response.body)["posts"].map { |post| post["slug"] }
refute_includes slugs, "later"
end
def test_json_feed_endpoint
get "/api/volumen/feed.json"
assert_predicate last_response, :ok?
data = JSON.parse(last_response.body)
assert_equal "https://jsonfeed.org/version/1.1", data["version"]
assert_equal "My Blog", data["title"]
assert_equal 1, data["items"].length
assert_equal "Hello", data["items"].first["title"]
assert_includes data["items"].first["content_html"], "<strong>world</strong>"
refute_includes data["items"].map { |i| i["title"] }, "Draft"
end
def test_post_summary_exposes_fediverse_creator
File.write(File.join(@dir, "attributed.md"), <<~POST)
+++
title = "Attributed"
slug = "attributed"
fediverse_creator = "@ada@lovelace.org"
+++
Body.
POST
get "/api/volumen/posts/attributed"
assert_predicate last_response, :ok?
data = JSON.parse(last_response.body)
assert_equal "@ada@lovelace.org", data["fediverse_creator"]
end
def test_post_summary_fediverse_creator_is_null_when_not_set
get "/api/volumen/posts/hello"
assert_predicate last_response, :ok?
assert_nil JSON.parse(last_response.body)["fediverse_creator"]
end
def test_posts_list_summary_exposes_fediverse_creator
File.write(File.join(@dir, "fed.md"), <<~POST)
+++
title = "Fed"
slug = "fed"
fediverse_creator = "@user@example.social"
+++
Body.
POST
get "/api/volumen/posts"
data = JSON.parse(last_response.body)
fed = data["posts"].find { |post| post["slug"] == "fed" }
assert_equal "@user@example.social", fed["fediverse_creator"]
end
def test_site_endpoint_exposes_fediverse_creator_default
get "/api/volumen/site"
assert_predicate last_response, :ok?
assert JSON.parse(last_response.body).key?("fediverse_creator")
end
def test_rss_feed_includes_dc_creator_when_set
File.write(File.join(@dir, "rss.md"), <<~POST)
+++
title = "Rss"
slug = "rss"
fediverse_creator = "@rss@example.com"
+++
Body.
POST
get "/api/volumen/feed.xml"
assert_includes last_response.body, "<dc:creator>@rss@example.com</dc:creator>"
assert_includes last_response.body, "xmlns:dc=\"http://purl.org/dc/elements/1.1/\""
end
def test_rss_feed_omits_dc_creator_when_not_set
get "/api/volumen/feed.xml"
refute_includes last_response.body, "<dc:creator>"
end
def test_json_feed_includes_authors_from_post
File.write(File.join(@dir, "jsonfed.md"), <<~POST)
+++
title = "Jsonfed"
slug = "jsonfed"
fediverse_creator = "@jf@example.io"
+++
Body.
POST
get "/api/volumen/feed.json"
item = JSON.parse(last_response.body)["items"].find { |i| i["id"] == "https://example.com/jsonfed" }
assert_equal [{ "name" => "@jf@example.io" }], item["authors"]
end
def test_json_feed_falls_back_to_site_default_fediverse_creator
Dir.chdir(@dir) do
File.write("config.toml", <<~TOML)
[site]
fediverse_creator = "@owner@example.com"
TOML
end
@config = Volumen::Config.load(
path: File.join(@dir, "config.toml"),
overrides: { content: @dir }
)
get "/api/volumen/feed.json"
items = JSON.parse(last_response.body)["items"]
expected = [{ "name" => "@owner@example.com" }]
assert(items.all? { |i| i["authors"] == expected })
end
def test_search_by_title
get "/api/volumen/posts?q=Hello"
data = JSON.parse(last_response.body)
assert_equal 1, data["total"]
assert_equal "hello", data["posts"].first["slug"]
end
def test_search_by_body
get "/api/volumen/posts?q=world"
data = JSON.parse(last_response.body)
assert_equal 1, data["total"]
end
def test_search_no_match
get "/api/volumen/posts?q=nonexistent"
data = JSON.parse(last_response.body)
assert_equal 0, data["total"]
end
def test_search_is_case_insensitive
get "/api/volumen/posts?q=HELLO"
data = JSON.parse(last_response.body)
assert_equal 1, data["total"]
end
end