mirror of
https://github.com/samsonjs/samhuri.net.git
synced 2026-04-27 14:57:40 +00:00
Make plugins explicit and improve coverage workflows
This commit is contained in:
parent
3b8ef3169e
commit
664a458c35
6 changed files with 278 additions and 27 deletions
|
|
@ -24,8 +24,10 @@ Keep new code under the existing `Pressa` module structure (for example `lib/pos
|
||||||
- `rbenv exec bundle exec bake publish_beta|publish`: build and rsync `www/` to remote host.
|
- `rbenv exec bundle exec bake publish_beta|publish`: build and rsync `www/` to remote host.
|
||||||
- `rbenv exec bundle exec bake clean`: remove `www/`.
|
- `rbenv exec bundle exec bake clean`: remove `www/`.
|
||||||
- `rbenv exec bundle exec bake test`: run test suite.
|
- `rbenv exec bundle exec bake test`: run test suite.
|
||||||
- `rbenv exec bundle exec standardrb` or `rbenv exec bundle exec bake lint`: lint code.
|
- `rbenv exec bundle exec bake lint`: lint code.
|
||||||
- `rbenv exec bundle exec bake lint_fix`: auto-fix lint issues.
|
- `rbenv exec bundle exec bake lint_fix`: auto-fix lint issues.
|
||||||
|
- `rbenv exec bundle exec bake coverage`: run tests and report `lib/` line coverage.
|
||||||
|
- `rbenv exec bundle exec bake coverage_regression baseline=merge-base`: compare coverage to a baseline and fail on regression (override `baseline` as needed).
|
||||||
|
|
||||||
## Draft Workflow
|
## Draft Workflow
|
||||||
- `rbenv exec bundle exec bake new_draft "Post Title"` creates `public/drafts/<slug>.md`.
|
- `rbenv exec bundle exec bake new_draft "Post Title"` creates `public/drafts/<slug>.md`.
|
||||||
|
|
@ -44,7 +46,7 @@ Optional keys include `Tags`, `Link`, `Scripts`, and `Styles`.
|
||||||
|
|
||||||
## Coding Style & Naming Conventions
|
## Coding Style & Naming Conventions
|
||||||
- Ruby version: `4.0.1` (see `.ruby-version` and `Gemfile`).
|
- Ruby version: `4.0.1` (see `.ruby-version` and `Gemfile`).
|
||||||
- Follow idiomatic Ruby style and keep code `standardrb`-clean.
|
- Follow idiomatic Ruby style and keep code `bake lint`-clean.
|
||||||
- Use 2-space indentation and descriptive `snake_case` names for methods/variables, `UpperCamelCase` for classes/modules.
|
- Use 2-space indentation and descriptive `snake_case` names for methods/variables, `UpperCamelCase` for classes/modules.
|
||||||
- Prefer small, focused classes for plugins, views, renderers, and config loaders.
|
- Prefer small, focused classes for plugins, views, renderers, and config loaders.
|
||||||
- Do not hand-edit generated files in `www/`.
|
- Do not hand-edit generated files in `www/`.
|
||||||
|
|
@ -54,7 +56,8 @@ Optional keys include `Tags`, `Link`, `Scripts`, and `Styles`.
|
||||||
- Add regression specs for parser, rendering, feed, and generator behavior changes.
|
- Add regression specs for parser, rendering, feed, and generator behavior changes.
|
||||||
- Before submitting, run:
|
- Before submitting, run:
|
||||||
- `rbenv exec bundle exec bake test`
|
- `rbenv exec bundle exec bake test`
|
||||||
- `rbenv exec bundle exec standardrb`
|
- `rbenv exec bundle exec bake coverage`
|
||||||
|
- `rbenv exec bundle exec bake lint`
|
||||||
- `rbenv exec bundle exec bake debug`
|
- `rbenv exec bundle exec bake debug`
|
||||||
|
|
||||||
## Commit & Pull Request Guidelines
|
## Commit & Pull Request Guidelines
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ rbenv exec bundle exec bake serve # serve www/ locally
|
||||||
|
|
||||||
Site metadata and project data are configured with TOML files at the repository root:
|
Site metadata and project data are configured with TOML files at the repository root:
|
||||||
|
|
||||||
- `site.toml`: site identity, default scripts/styles, and `projects_plugin` assets.
|
- `site.toml`: site identity, default scripts/styles, and a `plugins` list (for example `["posts", "projects"]`), plus `projects_plugin` assets when that plugin is enabled.
|
||||||
- `projects.toml`: project listing entries using `[[projects]]`.
|
- `projects.toml`: project listing entries using `[[projects]]`.
|
||||||
|
|
||||||
`Pressa.create_site` loads both files from the provided `source_path` and still supports URL overrides for `debug`, `beta`, and `release` builds.
|
`Pressa.create_site` loads both files from the provided `source_path` and still supports URL overrides for `debug`, `beta`, and `release` builds.
|
||||||
|
|
@ -53,9 +53,10 @@ Site metadata and project data are configured with TOML files at the repository
|
||||||
If this workflow seems like a good fit, here is the minimum to make it your own:
|
If this workflow seems like a good fit, here is the minimum to make it your own:
|
||||||
|
|
||||||
- Update `site.toml` with your site identity (`author`, `email`, `title`, `description`, `url`) and any global `scripts` / `styles`.
|
- Update `site.toml` with your site identity (`author`, `email`, `title`, `description`, `url`) and any global `scripts` / `styles`.
|
||||||
|
- Set `plugins` in `site.toml` to explicitly enable features (`"posts"`, `"projects"`). Safe default if omitted is no plugins.
|
||||||
- Define your projects in `projects.toml` using `[[projects]]` entries with `name`, `title`, `description`, and `url`.
|
- Define your projects in `projects.toml` using `[[projects]]` entries with `name`, `title`, `description`, and `url`.
|
||||||
- Configure project-page-only assets in `site.toml` under `[projects_plugin]` (`scripts` and `styles`).
|
- Configure project-page-only assets in `site.toml` under `[projects_plugin]` (`scripts` and `styles`) when using the `"projects"` plugin.
|
||||||
- Keep the built-in plugins (`Posts::Plugin` and `Projects::Plugin`) or add your own by implementing `Pressa::Plugin` in `lib/` and registering it in `lib/config/loader.rb`.
|
- Add custom plugins by implementing `Pressa::Plugin` in `lib/` and registering them in `lib/config/loader.rb`.
|
||||||
- Adjust rendering and layout in `lib/views/` and the static content in `public/` as needed.
|
- Adjust rendering and layout in `lib/views/` and the static content in `public/` as needed.
|
||||||
|
|
||||||
Other targets:
|
Other targets:
|
||||||
|
|
|
||||||
136
bake.rb
136
bake.rb
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
require "etc"
|
require "etc"
|
||||||
require "fileutils"
|
require "fileutils"
|
||||||
|
require "open3"
|
||||||
|
require "tmpdir"
|
||||||
|
|
||||||
DRAFTS_DIR = "public/drafts".freeze
|
DRAFTS_DIR = "public/drafts".freeze
|
||||||
PUBLISH_HOST = "mudge".freeze
|
PUBLISH_HOST = "mudge".freeze
|
||||||
|
|
@ -136,9 +138,9 @@ def clean
|
||||||
puts "Cleaned www/ directory"
|
puts "Cleaned www/ directory"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Default task: run tests and lint.
|
# Default task: run coverage and lint.
|
||||||
def default
|
def default
|
||||||
test
|
coverage
|
||||||
lint
|
lint
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -178,6 +180,37 @@ def coverage(lowest: 10)
|
||||||
run_coverage(test_files: test_file_list, lowest_count:)
|
run_coverage(test_files: test_file_list, lowest_count:)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Compare line coverage for files under lib/ against a baseline and fail on regression.
|
||||||
|
# @parameter baseline [String] Baseline ref, or "merge-base" (default) to compare against merge-base with remote default branch.
|
||||||
|
# @parameter lowest [Integer] Number of lowest-covered files to print for the current checkout (default: 10, use 0 to hide).
|
||||||
|
def coverage_regression(baseline: "merge-base", lowest: 10)
|
||||||
|
lowest_count = Integer(lowest)
|
||||||
|
abort "Error: lowest must be >= 0." if lowest_count.negative?
|
||||||
|
|
||||||
|
baseline_ref = resolve_coverage_baseline_ref(baseline)
|
||||||
|
baseline_commit = capture_command("git", "rev-parse", "--short", baseline_ref).strip
|
||||||
|
|
||||||
|
puts "Running coverage for current checkout..."
|
||||||
|
current_output = capture_coverage_output(test_files: test_file_list, lowest_count:, chdir: Dir.pwd)
|
||||||
|
print current_output
|
||||||
|
current_percent = parse_coverage_percent(current_output)
|
||||||
|
|
||||||
|
puts "Running coverage for baseline #{baseline_ref} (#{baseline_commit})..."
|
||||||
|
baseline_percent = with_temporary_worktree(ref: baseline_ref) do |worktree_path|
|
||||||
|
baseline_tests = test_file_list(chdir: worktree_path)
|
||||||
|
baseline_output = capture_coverage_output(test_files: baseline_tests, lowest_count: 0, chdir: worktree_path)
|
||||||
|
parse_coverage_percent(baseline_output)
|
||||||
|
end
|
||||||
|
|
||||||
|
delta = current_percent - baseline_percent
|
||||||
|
puts format("Baseline coverage (%s %s): %.2f%%", baseline_ref, baseline_commit, baseline_percent)
|
||||||
|
puts format("Coverage delta: %+0.2f%%", delta)
|
||||||
|
|
||||||
|
return unless delta.negative?
|
||||||
|
|
||||||
|
abort format("Error: coverage regressed by %.2f%% against %s (%s).", -delta, baseline_ref, baseline_commit)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def run_test_suite(test_files)
|
def run_test_suite(test_files)
|
||||||
|
|
@ -185,7 +218,19 @@ def run_test_suite(test_files)
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_coverage(test_files:, lowest_count:)
|
def run_coverage(test_files:, lowest_count:)
|
||||||
coverage_script = <<~RUBY
|
output = capture_coverage_output(test_files:, lowest_count:, chdir: Dir.pwd)
|
||||||
|
print output
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_file_list(chdir: Dir.pwd)
|
||||||
|
test_files = Dir.chdir(chdir) { Dir.glob("spec/**/*_test.rb").sort }
|
||||||
|
abort "Error: no tests found in spec/**/*_test.rb under #{chdir}" if test_files.empty?
|
||||||
|
|
||||||
|
test_files
|
||||||
|
end
|
||||||
|
|
||||||
|
def coverage_script(lowest_count:)
|
||||||
|
<<~RUBY
|
||||||
require "coverage"
|
require "coverage"
|
||||||
|
|
||||||
root = Dir.pwd
|
root = Dir.pwd
|
||||||
|
|
@ -226,15 +271,88 @@ def run_coverage(test_files:, lowest_count:)
|
||||||
|
|
||||||
ARGV.each { |file| require File.expand_path(file) }
|
ARGV.each { |file| require File.expand_path(file) }
|
||||||
RUBY
|
RUBY
|
||||||
|
|
||||||
run_command("ruby", "-Ilib", "-Ispec", "-e", coverage_script, *test_files)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_file_list
|
def capture_coverage_output(test_files:, lowest_count:, chdir:)
|
||||||
test_files = Dir.glob("spec/**/*_test.rb").sort
|
capture_command("ruby", "-Ilib", "-Ispec", "-e", coverage_script(lowest_count:), *test_files, chdir:)
|
||||||
abort "Error: no tests found in spec/**/*_test.rb" if test_files.empty?
|
end
|
||||||
|
|
||||||
test_files
|
def parse_coverage_percent(output)
|
||||||
|
match = output.match(/Coverage \(lib\):\s+([0-9]+\.[0-9]+)%/)
|
||||||
|
abort "Error: unable to parse coverage output." unless match
|
||||||
|
|
||||||
|
Float(match[1])
|
||||||
|
end
|
||||||
|
|
||||||
|
def resolve_coverage_baseline_ref(baseline)
|
||||||
|
baseline_name = baseline.to_s.strip
|
||||||
|
abort "Error: baseline cannot be empty." if baseline_name.empty?
|
||||||
|
|
||||||
|
return coverage_merge_base_ref if baseline_name == "merge-base"
|
||||||
|
|
||||||
|
baseline_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def coverage_merge_base_ref
|
||||||
|
remote = preferred_remote
|
||||||
|
remote_head_ref = remote_default_branch_ref(remote)
|
||||||
|
merge_base = capture_command("git", "merge-base", "HEAD", remote_head_ref).strip
|
||||||
|
abort "Error: could not resolve merge-base with #{remote_head_ref}." if merge_base.empty?
|
||||||
|
|
||||||
|
merge_base
|
||||||
|
end
|
||||||
|
|
||||||
|
def preferred_remote
|
||||||
|
upstream = capture_command_optional("git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}").strip
|
||||||
|
upstream_remote = upstream.split("/").first unless upstream.empty?
|
||||||
|
return upstream_remote if upstream_remote && !upstream_remote.empty?
|
||||||
|
|
||||||
|
remotes = capture_command("git", "remote").lines.map(&:strip).reject(&:empty?)
|
||||||
|
abort "Error: no git remotes configured; pass baseline=<ref>." if remotes.empty?
|
||||||
|
|
||||||
|
remotes.include?("origin") ? "origin" : remotes.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def remote_default_branch_ref(remote)
|
||||||
|
symbolic = capture_command_optional("git", "symbolic-ref", "--quiet", "refs/remotes/#{remote}/HEAD").strip
|
||||||
|
if symbolic.empty?
|
||||||
|
fallback = "#{remote}/main"
|
||||||
|
capture_command("git", "rev-parse", "--verify", fallback)
|
||||||
|
return fallback
|
||||||
|
end
|
||||||
|
|
||||||
|
symbolic.sub("refs/remotes/", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_temporary_worktree(ref:)
|
||||||
|
temp_root = Dir.mktmpdir("coverage-baseline-")
|
||||||
|
worktree_path = File.join(temp_root, "worktree")
|
||||||
|
|
||||||
|
run_command("git", "worktree", "add", "--detach", worktree_path, ref)
|
||||||
|
begin
|
||||||
|
yield worktree_path
|
||||||
|
ensure
|
||||||
|
system("git", "worktree", "remove", "--force", worktree_path)
|
||||||
|
FileUtils.rm_rf(temp_root)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def capture_command(*command, chdir: Dir.pwd)
|
||||||
|
stdout, stderr, status = Dir.chdir(chdir) { Open3.capture3(*command) }
|
||||||
|
output = +""
|
||||||
|
output << stdout unless stdout.empty?
|
||||||
|
output << stderr unless stderr.empty?
|
||||||
|
abort "Error: command failed: #{command.join(" ")}\n#{output}" unless status.success?
|
||||||
|
|
||||||
|
output
|
||||||
|
end
|
||||||
|
|
||||||
|
def capture_command_optional(*command, chdir: Dir.pwd)
|
||||||
|
stdout, stderr, status = Dir.chdir(chdir) { Open3.capture3(*command) }
|
||||||
|
return stdout if status.success?
|
||||||
|
return "" if stderr.include?("no upstream configured") || stderr.include?("is not a symbolic ref")
|
||||||
|
|
||||||
|
""
|
||||||
end
|
end
|
||||||
|
|
||||||
# Build the site with specified URL
|
# Build the site with specified URL
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,11 @@ module Pressa
|
||||||
|
|
||||||
def build_site(url_override: nil)
|
def build_site(url_override: nil)
|
||||||
site_config = load_toml("site.toml")
|
site_config = load_toml("site.toml")
|
||||||
projects_config = load_toml("projects.toml")
|
|
||||||
|
|
||||||
validate_required!(site_config, REQUIRED_SITE_KEYS, context: "site.toml")
|
validate_required!(site_config, REQUIRED_SITE_KEYS, context: "site.toml")
|
||||||
|
|
||||||
site_url = url_override || site_config["url"]
|
site_url = url_override || site_config["url"]
|
||||||
projects_plugin = hash_or_empty(site_config["projects_plugin"], "site.toml projects_plugin")
|
plugins = build_plugins(site_config)
|
||||||
|
|
||||||
projects = build_projects(projects_config)
|
|
||||||
|
|
||||||
Site.new(
|
Site.new(
|
||||||
author: site_config["author"],
|
author: site_config["author"],
|
||||||
|
|
@ -36,14 +33,7 @@ module Pressa
|
||||||
image_url: normalize_image_url(site_config["image_url"], site_url),
|
image_url: normalize_image_url(site_config["image_url"], site_url),
|
||||||
scripts: build_scripts(site_config["scripts"], context: "site.toml scripts"),
|
scripts: build_scripts(site_config["scripts"], context: "site.toml scripts"),
|
||||||
styles: build_styles(site_config["styles"], context: "site.toml styles"),
|
styles: build_styles(site_config["styles"], context: "site.toml styles"),
|
||||||
plugins: [
|
plugins:,
|
||||||
Posts::Plugin.new,
|
|
||||||
Projects::Plugin.new(
|
|
||||||
projects:,
|
|
||||||
scripts: build_scripts(projects_plugin["scripts"], context: "site.toml projects_plugin.scripts"),
|
|
||||||
styles: build_styles(projects_plugin["styles"], context: "site.toml projects_plugin.styles")
|
|
||||||
)
|
|
||||||
],
|
|
||||||
renderers: [
|
renderers: [
|
||||||
Utils::MarkdownRenderer.new
|
Utils::MarkdownRenderer.new
|
||||||
]
|
]
|
||||||
|
|
@ -90,6 +80,54 @@ module Pressa
|
||||||
raise ValidationError, "Missing required #{context} keys: #{missing.join(", ")}"
|
raise ValidationError, "Missing required #{context} keys: #{missing.join(", ")}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_plugins(site_config)
|
||||||
|
plugin_names = parse_plugin_names(site_config["plugins"])
|
||||||
|
|
||||||
|
plugin_names.map.with_index do |plugin_name, index|
|
||||||
|
case plugin_name
|
||||||
|
when "posts"
|
||||||
|
Posts::Plugin.new
|
||||||
|
when "projects"
|
||||||
|
build_projects_plugin(site_config)
|
||||||
|
else
|
||||||
|
raise ValidationError, "Unknown plugin '#{plugin_name}' at site.toml plugins[#{index}]"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_plugin_names(value)
|
||||||
|
return [] if value.nil?
|
||||||
|
raise ValidationError, "Expected site.toml plugins to be an array" unless value.is_a?(Array)
|
||||||
|
|
||||||
|
seen = {}
|
||||||
|
|
||||||
|
value.map.with_index do |plugin_name, index|
|
||||||
|
unless plugin_name.is_a?(String) && !plugin_name.strip.empty?
|
||||||
|
raise ValidationError, "Expected site.toml plugins[#{index}] to be a non-empty String"
|
||||||
|
end
|
||||||
|
|
||||||
|
normalized_plugin_name = plugin_name.strip
|
||||||
|
if seen[normalized_plugin_name]
|
||||||
|
raise ValidationError, "Duplicate plugin '#{normalized_plugin_name}' in site.toml plugins"
|
||||||
|
end
|
||||||
|
seen[normalized_plugin_name] = true
|
||||||
|
|
||||||
|
normalized_plugin_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_projects_plugin(site_config)
|
||||||
|
projects_plugin = hash_or_empty(site_config["projects_plugin"], "site.toml projects_plugin")
|
||||||
|
projects_config = load_toml("projects.toml")
|
||||||
|
projects = build_projects(projects_config)
|
||||||
|
|
||||||
|
Projects::Plugin.new(
|
||||||
|
projects:,
|
||||||
|
scripts: build_scripts(projects_plugin["scripts"], context: "site.toml projects_plugin.scripts"),
|
||||||
|
styles: build_styles(projects_plugin["styles"], context: "site.toml projects_plugin.styles")
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
def hash_or_empty(value, context)
|
def hash_or_empty(value, context)
|
||||||
return {} if value.nil?
|
return {} if value.nil?
|
||||||
return value if value.is_a?(Hash)
|
return value if value.is_a?(Hash)
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ url = "https://samhuri.net"
|
||||||
image_url = "/images/me.jpg"
|
image_url = "/images/me.jpg"
|
||||||
scripts = []
|
scripts = []
|
||||||
styles = ["css/normalize.css", "css/style.css", "css/syntax.css"]
|
styles = ["css/normalize.css", "css/style.css", "css/syntax.css"]
|
||||||
|
plugins = ["posts", "projects"]
|
||||||
|
|
||||||
[projects_plugin]
|
[projects_plugin]
|
||||||
scripts = [
|
scripts = [
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,90 @@ class Pressa::Config::LoaderTest < Minitest::Test
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_build_site_defaults_to_no_plugins_when_plugins_key_is_missing
|
||||||
|
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"
|
||||||
|
TOML
|
||||||
|
|
||||||
|
loader = Pressa::Config::Loader.new(source_path: dir)
|
||||||
|
site = loader.build_site
|
||||||
|
assert_empty(site.plugins)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_build_site_raises_for_invalid_plugins_type
|
||||||
|
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"
|
||||||
|
plugins = "posts"
|
||||||
|
TOML
|
||||||
|
|
||||||
|
loader = Pressa::Config::Loader.new(source_path: dir)
|
||||||
|
error = assert_raises(Pressa::Config::ValidationError) { loader.build_site }
|
||||||
|
assert_match(/Expected site\.toml plugins to be an array/, error.message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_build_site_raises_for_unknown_plugin_name
|
||||||
|
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"
|
||||||
|
plugins = ["wat"]
|
||||||
|
TOML
|
||||||
|
|
||||||
|
loader = Pressa::Config::Loader.new(source_path: dir)
|
||||||
|
error = assert_raises(Pressa::Config::ValidationError) { loader.build_site }
|
||||||
|
assert_match(/Unknown plugin 'wat'/, error.message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_build_site_raises_for_empty_plugin_name
|
||||||
|
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"
|
||||||
|
plugins = [""]
|
||||||
|
TOML
|
||||||
|
|
||||||
|
loader = Pressa::Config::Loader.new(source_path: dir)
|
||||||
|
error = assert_raises(Pressa::Config::ValidationError) { loader.build_site }
|
||||||
|
assert_match(/Expected site\.toml plugins\[0\] to be a non-empty String/, error.message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_build_site_raises_for_duplicate_plugins
|
||||||
|
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"
|
||||||
|
plugins = ["posts", "posts"]
|
||||||
|
TOML
|
||||||
|
|
||||||
|
loader = Pressa::Config::Loader.new(source_path: dir)
|
||||||
|
error = assert_raises(Pressa::Config::ValidationError) { loader.build_site }
|
||||||
|
assert_match(/Duplicate plugin 'posts' in site\.toml plugins/, error.message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_build_site_raises_for_missing_projects_array
|
def test_build_site_raises_for_missing_projects_array
|
||||||
Dir.mktmpdir do |dir|
|
Dir.mktmpdir do |dir|
|
||||||
File.write(File.join(dir, "site.toml"), <<~TOML)
|
File.write(File.join(dir, "site.toml"), <<~TOML)
|
||||||
|
|
@ -48,6 +132,7 @@ class Pressa::Config::LoaderTest < Minitest::Test
|
||||||
title = "samhuri.net"
|
title = "samhuri.net"
|
||||||
description = "blog"
|
description = "blog"
|
||||||
url = "https://samhuri.net"
|
url = "https://samhuri.net"
|
||||||
|
plugins = ["projects"]
|
||||||
TOML
|
TOML
|
||||||
File.write(File.join(dir, "projects.toml"), "title = \"no projects\"\n")
|
File.write(File.join(dir, "projects.toml"), "title = \"no projects\"\n")
|
||||||
|
|
||||||
|
|
@ -65,6 +150,7 @@ class Pressa::Config::LoaderTest < Minitest::Test
|
||||||
title = "samhuri.net"
|
title = "samhuri.net"
|
||||||
description = "blog"
|
description = "blog"
|
||||||
url = "https://samhuri.net"
|
url = "https://samhuri.net"
|
||||||
|
plugins = ["projects"]
|
||||||
TOML
|
TOML
|
||||||
File.write(File.join(dir, "projects.toml"), <<~TOML)
|
File.write(File.join(dir, "projects.toml"), <<~TOML)
|
||||||
projects = [1]
|
projects = [1]
|
||||||
|
|
@ -84,6 +170,7 @@ class Pressa::Config::LoaderTest < Minitest::Test
|
||||||
title = "samhuri.net"
|
title = "samhuri.net"
|
||||||
description = "blog"
|
description = "blog"
|
||||||
url = "https://samhuri.net"
|
url = "https://samhuri.net"
|
||||||
|
plugins = ["projects"]
|
||||||
projects_plugin = []
|
projects_plugin = []
|
||||||
TOML
|
TOML
|
||||||
File.write(File.join(dir, "projects.toml"), <<~TOML)
|
File.write(File.join(dir, "projects.toml"), <<~TOML)
|
||||||
|
|
@ -148,6 +235,7 @@ class Pressa::Config::LoaderTest < Minitest::Test
|
||||||
image_url = "https://images.example.net/me.jpg"
|
image_url = "https://images.example.net/me.jpg"
|
||||||
scripts = [{"src": "/js/site.js", "defer": false}]
|
scripts = [{"src": "/js/site.js", "defer": false}]
|
||||||
styles = [{"href": "/css/site.css"}]
|
styles = [{"href": "/css/site.css"}]
|
||||||
|
plugins = ["posts", "projects"]
|
||||||
|
|
||||||
[projects_plugin]
|
[projects_plugin]
|
||||||
scripts = [{"src": "/js/projects.js", "defer": true}]
|
scripts = [{"src": "/js/projects.js", "defer": true}]
|
||||||
|
|
@ -240,6 +328,7 @@ class Pressa::Config::LoaderTest < Minitest::Test
|
||||||
title = "samhuri.net"
|
title = "samhuri.net"
|
||||||
description = "blog"
|
description = "blog"
|
||||||
url = "https://samhuri.net"
|
url = "https://samhuri.net"
|
||||||
|
plugins = ["projects"]
|
||||||
|
|
||||||
[projects_plugin]
|
[projects_plugin]
|
||||||
scripts = "js/projects.js"
|
scripts = "js/projects.js"
|
||||||
|
|
@ -262,6 +351,7 @@ class Pressa::Config::LoaderTest < Minitest::Test
|
||||||
image_url = "/images/me.jpg"
|
image_url = "/images/me.jpg"
|
||||||
scripts = []
|
scripts = []
|
||||||
styles = ["css/style.css"]
|
styles = ["css/style.css"]
|
||||||
|
plugins = ["posts", "projects"]
|
||||||
|
|
||||||
[projects_plugin]
|
[projects_plugin]
|
||||||
scripts = ["js/projects.js"]
|
scripts = ["js/projects.js"]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue