diff --git a/Gemfile b/Gemfile index d978e31..43357d1 100644 --- a/Gemfile +++ b/Gemfile @@ -12,8 +12,7 @@ gem "bake", "~> 0.20" gem "nokogiri", "~> 1.18" group :development, :test do - gem "rspec", "~> 3.13" gem "guard", "~> 2.18" - gem "guard-rspec", "~> 4.7" + gem "minitest", "~> 6.0" gem "standard", "~> 1.43" end diff --git a/Gemfile.lock b/Gemfile.lock index 9f0d135..e03c171 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -13,7 +13,6 @@ GEM fiber-annotation fiber-local (~> 1.1) json - diff-lcs (1.6.2) dry-core (1.2.0) concurrent-ruby (~> 1.0) logger @@ -63,11 +62,6 @@ GEM pry (>= 0.13.0) shellany (~> 0.0) thor (>= 0.18.1) - guard-compat (1.2.1) - guard-rspec (4.7.3) - guard (~> 2.1) - guard-compat (~> 1.1) - rspec (>= 2.99.0, < 4.0) ice_nine (0.11.2) io-console (0.8.2) json (2.18.1) @@ -86,6 +80,8 @@ GEM mapping (1.1.3) method_source (1.1.0) mini_portile2 (2.8.9) + minitest (6.0.0) + prism (~> 1.5) nenv (0.3.0) nokogiri (1.19.0) mini_portile2 (~> 2.8.2) @@ -134,19 +130,6 @@ GEM io-console (~> 0.5) rexml (3.4.4) rouge (4.7.0) - rspec (3.13.2) - rspec-core (~> 3.13.0) - rspec-expectations (~> 3.13.0) - rspec-mocks (~> 3.13.0) - rspec-core (3.13.6) - rspec-support (~> 3.13.0) - rspec-expectations (3.13.5) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.13.0) - rspec-mocks (3.13.7) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.13.0) - rspec-support (3.13.7) rubocop (1.82.1) json (~> 2.3) language_server-protocol (~> 3.17.0.2) @@ -194,7 +177,6 @@ PLATFORMS arm-linux-gnu arm-linux-musl arm64-darwin - ruby x86-linux-gnu x86-linux-musl x86_64-darwin @@ -206,13 +188,12 @@ DEPENDENCIES builder (~> 3.3) dry-struct (~> 1.8) guard (~> 2.18) - guard-rspec (~> 4.7) kramdown (~> 2.5) kramdown-parser-gfm (~> 1.1) + minitest (~> 6.0) nokogiri (~> 1.18) phlex (~> 2.3) rouge (~> 4.6) - rspec (~> 3.13) standard (~> 1.43) RUBY VERSION diff --git a/Readme.md b/Readme.md index d122e50..3216e89 100644 --- a/Readme.md +++ b/Readme.md @@ -78,7 +78,7 @@ Published posts in `posts/YYYY/MM/*.md` require YAML front matter keys: ## Tests And Lint ```bash -rbenv exec bundle exec rspec +rbenv exec bundle exec bake test rbenv exec bundle exec standardrb ``` diff --git a/bake.rb b/bake.rb index 0400276..8e7b372 100644 --- a/bake.rb +++ b/bake.rb @@ -136,9 +136,12 @@ def clean puts "Cleaned www/ directory" end -# Run RSpec tests +# Run Minitest tests def test - exec "bundle exec rspec" + test_files = Dir.glob("spec/**/*_test.rb").sort + abort "Error: no tests found in spec/**/*_test.rb" if test_files.empty? + + exec "ruby", "-Ilib", "-Ispec", "-e", "ARGV.each { |file| require File.expand_path(file) }", *test_files end # Run Guard for continuous testing diff --git a/spec/config/loader_spec.rb b/spec/config/loader_spec.rb deleted file mode 100644 index 396f055..0000000 --- a/spec/config/loader_spec.rb +++ /dev/null @@ -1,72 +0,0 @@ -require "spec_helper" -require "fileutils" -require "tmpdir" - -RSpec.describe Pressa::Config::Loader do - describe "#build_site" do - it "builds a site from site.toml and projects.toml" do - with_temp_config do |dir| - loader = described_class.new(source_path: dir) - site = loader.build_site - - expect(site.author).to eq("Sami Samhuri") - expect(site.url).to eq("https://samhuri.net") - expect(site.image_url).to eq("https://samhuri.net/images/me.jpg") - expect(site.styles.map(&:href)).to eq(["css/style.css"]) - - projects_plugin = site.plugins.find { |plugin| plugin.is_a?(Pressa::Projects::Plugin) } - expect(projects_plugin).not_to be_nil - expect(projects_plugin.scripts.map(&:src)).to eq(["js/projects.js"]) - end - end - - it "applies url_override and rewrites relative image_url with override host" do - with_temp_config do |dir| - loader = described_class.new(source_path: dir) - site = loader.build_site(url_override: "https://beta.samhuri.net") - - expect(site.url).to eq("https://beta.samhuri.net") - expect(site.image_url).to eq("https://beta.samhuri.net/images/me.jpg") - end - end - - it "raises a validation error for missing required site keys" do - Dir.mktmpdir do |dir| - File.write(File.join(dir, "site.toml"), "title = \"x\"\n") - File.write(File.join(dir, "projects.toml"), "") - - loader = described_class.new(source_path: dir) - expect { loader.build_site }.to raise_error(Pressa::Config::ValidationError, /Missing required site\.toml keys/) - end - end - end - - def with_temp_config - Dir.mktmpdir do |dir| - File.write(File.join(dir, "site.toml"), <<~TOML) - author = "Sami Samhuri" - email = "sami@samhuri.net" - title = "samhuri.net" - description = "blog" - url = "https://samhuri.net" - image_url = "/images/me.jpg" - scripts = [] - styles = ["css/style.css"] - - [projects_plugin] - scripts = ["js/projects.js"] - styles = [] - TOML - - File.write(File.join(dir, "projects.toml"), <<~TOML) - [[projects]] - name = "demo" - title = "demo" - description = "demo project" - url = "https://github.com/samsonjs/demo" - TOML - - yield dir - end - end -end diff --git a/spec/config/loader_test.rb b/spec/config/loader_test.rb new file mode 100644 index 0000000..640af06 --- /dev/null +++ b/spec/config/loader_test.rb @@ -0,0 +1,73 @@ +require "test_helper" +require "fileutils" +require "tmpdir" + +class Pressa::Config::LoaderTest < Minitest::Test + def test_build_site_builds_a_site_from_site_toml_and_projects_toml + with_temp_config do |dir| + loader = Pressa::Config::Loader.new(source_path: dir) + site = loader.build_site + + assert_equal("Sami Samhuri", site.author) + assert_equal("https://samhuri.net", site.url) + assert_equal("https://samhuri.net/images/me.jpg", site.image_url) + assert_equal(["css/style.css"], site.styles.map(&:href)) + + projects_plugin = site.plugins.find { |plugin| plugin.is_a?(Pressa::Projects::Plugin) } + refute_nil(projects_plugin) + assert_equal(["js/projects.js"], projects_plugin.scripts.map(&:src)) + end + end + + def test_build_site_applies_url_override_and_rewrites_relative_image_url_with_override_host + with_temp_config do |dir| + loader = Pressa::Config::Loader.new(source_path: dir) + site = loader.build_site(url_override: "https://beta.samhuri.net") + + assert_equal("https://beta.samhuri.net", site.url) + assert_equal("https://beta.samhuri.net/images/me.jpg", site.image_url) + end + end + + def test_build_site_raises_a_validation_error_for_missing_required_site_keys + Dir.mktmpdir do |dir| + File.write(File.join(dir, "site.toml"), "title = \"x\"\n") + File.write(File.join(dir, "projects.toml"), "") + + loader = Pressa::Config::Loader.new(source_path: dir) + error = assert_raises(Pressa::Config::ValidationError) { loader.build_site } + assert_match(/Missing required site\.toml keys/, error.message) + end + end + + private + + def with_temp_config + Dir.mktmpdir do |dir| + File.write(File.join(dir, "site.toml"), <<~TOML) + author = "Sami Samhuri" + email = "sami@samhuri.net" + title = "samhuri.net" + description = "blog" + url = "https://samhuri.net" + image_url = "/images/me.jpg" + scripts = [] + styles = ["css/style.css"] + + [projects_plugin] + scripts = ["js/projects.js"] + styles = [] + TOML + + File.write(File.join(dir, "projects.toml"), <<~TOML) + [[projects]] + name = "demo" + title = "demo" + description = "demo project" + url = "https://github.com/samsonjs/demo" + TOML + + yield dir + end + end +end diff --git a/spec/posts/json_feed_spec.rb b/spec/posts/json_feed_spec.rb deleted file mode 100644 index 70f249b..0000000 --- a/spec/posts/json_feed_spec.rb +++ /dev/null @@ -1,100 +0,0 @@ -require "spec_helper" -require "json" -require "tmpdir" - -RSpec.describe Pressa::Posts::JSONFeedWriter do - let(:site) do - Pressa::Site.new( - author: "Sami Samhuri", - email: "sami@samhuri.net", - title: "samhuri.net", - description: "blog", - url: "https://samhuri.net", - image_url: "https://samhuri.net/images/me.jpg" - ) - end - - let(:posts_by_year) { double("posts_by_year", recent_posts: [post]) } - let(:writer) { described_class.new(site:, posts_by_year:) } - - context "for link posts" do - let(:post) do - Pressa::Posts::Post.new( - slug: "github-flow-like-a-pro", - title: "GitHub Flow Like a Pro", - author: "Sami Samhuri", - date: DateTime.parse("2015-05-28T07:42:27-07:00"), - formatted_date: "28th May, 2015", - link: "http://haacked.com/archive/2014/07/28/github-flow-aliases/", - body: "

hello

", - excerpt: "hello...", - path: "/posts/2015/05/github-flow-like-a-pro" - ) - end - - it "uses permalink as url and keeps external_url for destination links" do - Dir.mktmpdir do |dir| - writer.write_feed(target_path: dir, limit: 30) - feed = JSON.parse(File.read(File.join(dir, "feed.json"))) - item = feed.fetch("items").first - - expect(item.fetch("id")).to eq("https://samhuri.net/posts/2015/05/github-flow-like-a-pro") - expect(item.fetch("url")).to eq("https://samhuri.net/posts/2015/05/github-flow-like-a-pro") - expect(item.fetch("external_url")).to eq("http://haacked.com/archive/2014/07/28/github-flow-aliases/") - end - end - end - - context "for regular posts" do - let(:post) do - Pressa::Posts::Post.new( - slug: "swift-optional-or", - title: "Swift Optional OR", - author: "Sami Samhuri", - date: DateTime.parse("2017-10-01T10:00:00-07:00"), - formatted_date: "1st October, 2017", - body: "

hello

", - excerpt: "hello...", - path: "/posts/2017/10/swift-optional-or" - ) - end - - it "omits external_url" do - Dir.mktmpdir do |dir| - writer.write_feed(target_path: dir, limit: 30) - feed = JSON.parse(File.read(File.join(dir, "feed.json"))) - item = feed.fetch("items").first - - expect(item.fetch("url")).to eq("https://samhuri.net/posts/2017/10/swift-optional-or") - expect(item).not_to have_key("external_url") - end - end - - it "expands root-relative links in content_html to absolute URLs" do - post_with_assets = Pressa::Posts::Post.new( - slug: "swift-optional-or", - title: "Swift Optional OR", - author: "Sami Samhuri", - date: DateTime.parse("2017-10-01T10:00:00-07:00"), - formatted_date: "1st October, 2017", - body: '

read

' \ - '

me

' \ - '

cdn

', - excerpt: "hello...", - path: "/posts/2017/10/swift-optional-or" - ) - allow(posts_by_year).to receive(:recent_posts).and_return([post_with_assets]) - - Dir.mktmpdir do |dir| - writer.write_feed(target_path: dir, limit: 30) - feed = JSON.parse(File.read(File.join(dir, "feed.json"))) - item = feed.fetch("items").first - content_html = item.fetch("content_html") - - expect(content_html).to include('href="https://samhuri.net/posts/2010/01/basics-of-the-mach-o-file-format"') - expect(content_html).to include('src="https://samhuri.net/images/me.jpg"') - expect(content_html).to include('href="//cdn.example.net/app.js"') - end - end - end -end diff --git a/spec/posts/json_feed_test.rb b/spec/posts/json_feed_test.rb new file mode 100644 index 0000000..6325432 --- /dev/null +++ b/spec/posts/json_feed_test.rb @@ -0,0 +1,115 @@ +require "test_helper" +require "json" +require "tmpdir" + +class Pressa::Posts::JSONFeedWriterTest < Minitest::Test + class PostsByYearStub + attr_accessor :posts + + def initialize(posts) + @posts = posts + end + + def recent_posts(_limit = 30) + @posts + end + end + + def setup + @site = Pressa::Site.new( + author: "Sami Samhuri", + email: "sami@samhuri.net", + title: "samhuri.net", + description: "blog", + url: "https://samhuri.net", + image_url: "https://samhuri.net/images/me.jpg" + ) + + @posts_by_year = PostsByYearStub.new([link_post]) + @writer = Pressa::Posts::JSONFeedWriter.new(site: @site, posts_by_year: @posts_by_year) + end + + def test_write_feed_for_link_posts_uses_permalink_as_url_and_keeps_external_url + Dir.mktmpdir do |dir| + @writer.write_feed(target_path: dir, limit: 30) + feed = JSON.parse(File.read(File.join(dir, "feed.json"))) + item = feed.fetch("items").first + + assert_equal("https://samhuri.net/posts/2015/05/github-flow-like-a-pro", item.fetch("id")) + assert_equal("https://samhuri.net/posts/2015/05/github-flow-like-a-pro", item.fetch("url")) + assert_equal("http://haacked.com/archive/2014/07/28/github-flow-aliases/", item.fetch("external_url")) + end + end + + def test_write_feed_for_regular_posts_omits_external_url + @posts_by_year.posts = [regular_post] + + Dir.mktmpdir do |dir| + @writer.write_feed(target_path: dir, limit: 30) + feed = JSON.parse(File.read(File.join(dir, "feed.json"))) + item = feed.fetch("items").first + + assert_equal("https://samhuri.net/posts/2017/10/swift-optional-or", item.fetch("url")) + refute(item.key?("external_url")) + end + end + + def test_write_feed_expands_root_relative_links_in_content_html + @posts_by_year.posts = [post_with_assets] + + Dir.mktmpdir do |dir| + @writer.write_feed(target_path: dir, limit: 30) + feed = JSON.parse(File.read(File.join(dir, "feed.json"))) + item = feed.fetch("items").first + content_html = item.fetch("content_html") + + assert_includes(content_html, 'href="https://samhuri.net/posts/2010/01/basics-of-the-mach-o-file-format"') + assert_includes(content_html, 'src="https://samhuri.net/images/me.jpg"') + assert_includes(content_html, 'href="//cdn.example.net/app.js"') + end + end + + private + + def link_post + Pressa::Posts::Post.new( + slug: "github-flow-like-a-pro", + title: "GitHub Flow Like a Pro", + author: "Sami Samhuri", + date: DateTime.parse("2015-05-28T07:42:27-07:00"), + formatted_date: "28th May, 2015", + link: "http://haacked.com/archive/2014/07/28/github-flow-aliases/", + body: "

hello

", + excerpt: "hello...", + path: "/posts/2015/05/github-flow-like-a-pro" + ) + end + + def regular_post + Pressa::Posts::Post.new( + slug: "swift-optional-or", + title: "Swift Optional OR", + author: "Sami Samhuri", + date: DateTime.parse("2017-10-01T10:00:00-07:00"), + formatted_date: "1st October, 2017", + body: "

hello

", + excerpt: "hello...", + path: "/posts/2017/10/swift-optional-or" + ) + end + + def post_with_assets + Pressa::Posts::Post.new( + slug: "swift-optional-or", + title: "Swift Optional OR", + author: "Sami Samhuri", + date: DateTime.parse("2017-10-01T10:00:00-07:00"), + formatted_date: "1st October, 2017", + body: '

read

' \ + '

me

' \ + '

cdn

', + excerpt: "hello...", + path: "/posts/2017/10/swift-optional-or" + ) + end +end diff --git a/spec/posts/metadata_spec.rb b/spec/posts/metadata_spec.rb deleted file mode 100644 index 831f212..0000000 --- a/spec/posts/metadata_spec.rb +++ /dev/null @@ -1,69 +0,0 @@ -require "spec_helper" - -RSpec.describe Pressa::Posts::PostMetadata do - describe ".parse" do - it "parses valid YAML front-matter" do - content = <<~MARKDOWN - --- - Title: Test Post - Author: Trent Reznor - Date: 5th November, 2025 - Timestamp: 2025-11-05T10:00:00-08:00 - Tags: Ruby, Testing - Scripts: highlight.js - Styles: code.css - Link: https://example.net/external - --- - - This is the post body. - MARKDOWN - - metadata = described_class.parse(content) - - expect(metadata.title).to eq("Test Post") - expect(metadata.author).to eq("Trent Reznor") - expect(metadata.formatted_date).to eq("5th November, 2025") - expect(metadata.date.year).to eq(2025) - expect(metadata.date.month).to eq(11) - expect(metadata.date.day).to eq(5) - expect(metadata.link).to eq("https://example.net/external") - expect(metadata.tags).to eq(["Ruby", "Testing"]) - expect(metadata.scripts.map(&:src)).to eq(["js/highlight.js"]) - expect(metadata.styles.map(&:href)).to eq(["css/code.css"]) - end - - it "raises error when required fields are missing" do - content = <<~MARKDOWN - --- - Title: Incomplete Post - --- - - Body content - MARKDOWN - - expect { - described_class.parse(content) - }.to raise_error(/Missing required fields/) - end - - it "handles posts without optional fields" do - content = <<~MARKDOWN - --- - Title: Simple Post - Author: Fat Mike - Date: 1st January, 2025 - Timestamp: 2025-01-01T12:00:00-08:00 - --- - - Simple content - MARKDOWN - - metadata = described_class.parse(content) - - expect(metadata.tags).to eq([]) - expect(metadata.scripts).to eq([]) - expect(metadata.styles).to eq([]) - expect(metadata.link).to be_nil - end - end -end diff --git a/spec/posts/metadata_test.rb b/spec/posts/metadata_test.rb new file mode 100644 index 0000000..45675ca --- /dev/null +++ b/spec/posts/metadata_test.rb @@ -0,0 +1,66 @@ +require "test_helper" + +class Pressa::Posts::PostMetadataTest < Minitest::Test + def test_parse_parses_valid_yaml_front_matter + content = <<~MARKDOWN + --- + Title: Test Post + Author: Trent Reznor + Date: 5th November, 2025 + Timestamp: 2025-11-05T10:00:00-08:00 + Tags: Ruby, Testing + Scripts: highlight.js + Styles: code.css + Link: https://example.net/external + --- + + This is the post body. + MARKDOWN + + metadata = Pressa::Posts::PostMetadata.parse(content) + + assert_equal("Test Post", metadata.title) + assert_equal("Trent Reznor", metadata.author) + assert_equal("5th November, 2025", metadata.formatted_date) + assert_equal(2025, metadata.date.year) + assert_equal(11, metadata.date.month) + assert_equal(5, metadata.date.day) + assert_equal("https://example.net/external", metadata.link) + assert_equal(["Ruby", "Testing"], metadata.tags) + assert_equal(["js/highlight.js"], metadata.scripts.map(&:src)) + assert_equal(["css/code.css"], metadata.styles.map(&:href)) + end + + def test_parse_raises_error_when_required_fields_are_missing + content = <<~MARKDOWN + --- + Title: Incomplete Post + --- + + Body content + MARKDOWN + + error = assert_raises(StandardError) { Pressa::Posts::PostMetadata.parse(content) } + assert_match(/Missing required fields/, error.message) + end + + def test_parse_handles_posts_without_optional_fields + content = <<~MARKDOWN + --- + Title: Simple Post + Author: Fat Mike + Date: 1st January, 2025 + Timestamp: 2025-01-01T12:00:00-08:00 + --- + + Simple content + MARKDOWN + + metadata = Pressa::Posts::PostMetadata.parse(content) + + assert_equal([], metadata.tags) + assert_equal([], metadata.scripts) + assert_equal([], metadata.styles) + assert_nil(metadata.link) + end +end diff --git a/spec/posts/repo_spec.rb b/spec/posts/repo_spec.rb deleted file mode 100644 index abd9030..0000000 --- a/spec/posts/repo_spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -require "spec_helper" -require "fileutils" -require "tmpdir" - -RSpec.describe Pressa::Posts::PostRepo do - let(:repo) { described_class.new } - - describe "#read_posts" do - it "reads and organizes posts by year and month" do - Dir.mktmpdir do |tmpdir| - posts_dir = File.join(tmpdir, "posts", "2025", "11") - FileUtils.mkdir_p(posts_dir) - - post_content = <<~MARKDOWN - --- - Title: Shredding in November - Author: Shaun White - Date: 5th November, 2025 - Timestamp: 2025-11-05T10:00:00-08:00 - --- - - Had an epic day at Whistler. The powder was deep and the lines were short. - MARKDOWN - - File.write(File.join(posts_dir, "shredding.md"), post_content) - - posts_by_year = repo.read_posts(File.join(tmpdir, "posts")) - - expect(posts_by_year.all_posts.length).to eq(1) - - post = posts_by_year.all_posts.first - expect(post.title).to eq("Shredding in November") - expect(post.author).to eq("Shaun White") - expect(post.slug).to eq("shredding") - expect(post.year).to eq(2025) - expect(post.month).to eq(11) - expect(post.path).to eq("/posts/2025/11/shredding") - end - end - - it "generates excerpts from post content" do - Dir.mktmpdir do |tmpdir| - posts_dir = File.join(tmpdir, "posts", "2025", "11") - FileUtils.mkdir_p(posts_dir) - - post_content = <<~MARKDOWN - --- - Title: Test Post - Author: Greg Graffin - Date: 5th November, 2025 - Timestamp: 2025-11-05T10:00:00-08:00 - --- - - This is a test post with some content. It should generate an excerpt. - - ![Image](image.png) - - More content with a [link](https://example.net). - MARKDOWN - - File.write(File.join(posts_dir, "test.md"), post_content) - - posts_by_year = repo.read_posts(File.join(tmpdir, "posts")) - post = posts_by_year.all_posts.first - - expect(post.excerpt).to include("test post") - expect(post.excerpt).not_to include("![") - expect(post.excerpt).to include("link") - expect(post.excerpt).not_to include("[link]") - end - end - end -end diff --git a/spec/posts/repo_test.rb b/spec/posts/repo_test.rb new file mode 100644 index 0000000..f741c62 --- /dev/null +++ b/spec/posts/repo_test.rb @@ -0,0 +1,73 @@ +require "test_helper" +require "fileutils" +require "tmpdir" + +class Pressa::Posts::PostRepoTest < Minitest::Test + def repo + @repo ||= Pressa::Posts::PostRepo.new + end + + def test_read_posts_reads_and_organizes_posts_by_year_and_month + Dir.mktmpdir do |tmpdir| + posts_dir = File.join(tmpdir, "posts", "2025", "11") + FileUtils.mkdir_p(posts_dir) + + post_content = <<~MARKDOWN + --- + Title: Shredding in November + Author: Shaun White + Date: 5th November, 2025 + Timestamp: 2025-11-05T10:00:00-08:00 + --- + + Had an epic day at Whistler. The powder was deep and the lines were short. + MARKDOWN + + File.write(File.join(posts_dir, "shredding.md"), post_content) + + posts_by_year = repo.read_posts(File.join(tmpdir, "posts")) + + assert_equal(1, posts_by_year.all_posts.length) + + post = posts_by_year.all_posts.first + assert_equal("Shredding in November", post.title) + assert_equal("Shaun White", post.author) + assert_equal("shredding", post.slug) + assert_equal(2025, post.year) + assert_equal(11, post.month) + assert_equal("/posts/2025/11/shredding", post.path) + end + end + + def test_read_posts_generates_excerpts_from_post_content + Dir.mktmpdir do |tmpdir| + posts_dir = File.join(tmpdir, "posts", "2025", "11") + FileUtils.mkdir_p(posts_dir) + + post_content = <<~MARKDOWN + --- + Title: Test Post + Author: Greg Graffin + Date: 5th November, 2025 + Timestamp: 2025-11-05T10:00:00-08:00 + --- + + This is a test post with some content. It should generate an excerpt. + + ![Image](image.png) + + More content with a [link](https://example.net). + MARKDOWN + + File.write(File.join(posts_dir, "test.md"), post_content) + + posts_by_year = repo.read_posts(File.join(tmpdir, "posts")) + post = posts_by_year.all_posts.first + + assert_includes(post.excerpt, "test post") + refute_includes(post.excerpt, "![") + assert_includes(post.excerpt, "link") + refute_includes(post.excerpt, "[link]") + end + end +end diff --git a/spec/site_generator_spec.rb b/spec/site_generator_test.rb similarity index 55% rename from spec/site_generator_spec.rb rename to spec/site_generator_test.rb index 9b04ab1..93b965b 100644 --- a/spec/site_generator_spec.rb +++ b/spec/site_generator_test.rb @@ -1,10 +1,10 @@ -require "spec_helper" +require "test_helper" require "fileutils" require "tmpdir" -RSpec.describe Pressa::SiteGenerator do - let(:site) do - Pressa::Site.new( +class Pressa::SiteGeneratorTest < Minitest::Test + def site + @site ||= Pressa::Site.new( author: "Sami Samhuri", email: "sami@samhuri.net", title: "samhuri.net", @@ -15,23 +15,23 @@ RSpec.describe Pressa::SiteGenerator do ) end - it "rejects a target path that matches the source path" do + def test_rejects_a_target_path_that_matches_the_source_path Dir.mktmpdir do |dir| FileUtils.mkdir_p(File.join(dir, "public")) source_file = File.join(dir, "public", "keep.txt") File.write(source_file, "safe") - generator = described_class.new(site:) - - expect { + generator = Pressa::SiteGenerator.new(site:) + error = assert_raises(ArgumentError) do generator.generate(source_path: dir, target_path: dir) - }.to raise_error(ArgumentError, /must not be the same as or contain source_path/) + end - expect(File.read(source_file)).to eq("safe") + assert_match(/must not be the same as or contain source_path/, error.message) + assert_equal("safe", File.read(source_file)) end end - it "does not copy ignored dotfiles from public" do + def test_does_not_copy_ignored_dotfiles_from_public Dir.mktmpdir do |dir| source_path = File.join(dir, "source") target_path = File.join(dir, "target") @@ -42,11 +42,11 @@ RSpec.describe Pressa::SiteGenerator do File.write(File.join(public_path, ".gitkeep"), "") File.write(File.join(public_path, "visible.txt"), "ok") - described_class.new(site:).generate(source_path:, target_path:) + Pressa::SiteGenerator.new(site:).generate(source_path:, target_path:) - expect(File.exist?(File.join(target_path, "visible.txt"))).to be(true) - expect(File.exist?(File.join(target_path, ".DS_Store"))).to be(false) - expect(File.exist?(File.join(target_path, ".gitkeep"))).to be(false) + assert(File.exist?(File.join(target_path, "visible.txt"))) + refute(File.exist?(File.join(target_path, ".DS_Store"))) + refute(File.exist?(File.join(target_path, ".gitkeep"))) end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 index ff5a9c9..0000000 --- a/spec/spec_helper.rb +++ /dev/null @@ -1,25 +0,0 @@ -require_relative "../lib/pressa" - -RSpec.configure do |config| - config.expect_with :rspec do |expectations| - expectations.include_chain_clauses_in_custom_matcher_descriptions = true - end - - config.mock_with :rspec do |mocks| - mocks.verify_partial_doubles = true - end - - config.shared_context_metadata_behavior = :apply_to_host_groups - config.filter_run_when_matching :focus - config.example_status_persistence_file_path = "spec/examples.txt" - config.disable_monkey_patching! - config.warnings = true - - if config.files_to_run.one? - config.default_formatter = "doc" - end - - config.profile_examples = 10 - config.order = :random - Kernel.srand config.seed -end diff --git a/spec/test_helper.rb b/spec/test_helper.rb new file mode 100644 index 0000000..6c45c43 --- /dev/null +++ b/spec/test_helper.rb @@ -0,0 +1,2 @@ +require_relative "../lib/pressa" +require "minitest/autorun" diff --git a/spec/views/layout_spec.rb b/spec/views/layout_test.rb similarity index 57% rename from spec/views/layout_spec.rb rename to spec/views/layout_test.rb index 741722f..5eac0f5 100644 --- a/spec/views/layout_spec.rb +++ b/spec/views/layout_test.rb @@ -1,7 +1,7 @@ -require "spec_helper" +require "test_helper" -RSpec.describe Pressa::Views::Layout do - let(:test_content_view) do +class Pressa::Views::LayoutTest < Minitest::Test + def test_content_view Class.new(Phlex::HTML) do def view_template article do @@ -11,8 +11,8 @@ RSpec.describe Pressa::Views::Layout do end.new end - let(:site) do - Pressa::Site.new( + def site + @site ||= Pressa::Site.new( author: "Sami Samhuri", email: "sami@samhuri.net", title: "samhuri.net", @@ -21,31 +21,31 @@ RSpec.describe Pressa::Views::Layout do ) end - it "renders child components as HTML instead of escaped text" do - html = described_class.new( + def test_rendering_child_components_as_html_instead_of_escaped_text + html = Pressa::Views::Layout.new( site:, canonical_url: "https://samhuri.net/posts/", content: test_content_view ).call - expect(html).to include("
") - expect(html).to include("

Hello

") - expect(html).not_to include("<article>") + assert_includes(html, "
") + assert_includes(html, "

Hello

") + refute_includes(html, "<article>") end - it "keeps escaping enabled for untrusted string fields" do + def test_keeps_escaping_enabled_for_untrusted_string_fields subtitle = "" - html = described_class.new( + html = Pressa::Views::Layout.new( site:, canonical_url: "https://samhuri.net/posts/", page_subtitle: subtitle, content: test_content_view ).call - expect(html).to include("samhuri.net: <img src=x onerror=alert(1)>") + assert_includes(html, "samhuri.net: <img src=x onerror=alert(1)>") end - it "preserves absolute stylesheet URLs" do + def test_preserves_absolute_stylesheet_urls cdn_site = Pressa::Site.new( author: "Sami Samhuri", email: "sami@samhuri.net", @@ -55,12 +55,12 @@ RSpec.describe Pressa::Views::Layout do styles: [Pressa::Stylesheet.new(href: "https://cdn.example.com/site.css")] ) - html = described_class.new( + html = Pressa::Views::Layout.new( site: cdn_site, canonical_url: "https://samhuri.net/posts/", content: test_content_view ).call - expect(html).to include(%()) + assert_includes(html, %()) end end