134 lines
3.8 KiB
Ruby
134 lines
3.8 KiB
Ruby
require_relative "test_helper"
|
|
require "json"
|
|
|
|
class FinderTest < Minitest::Test
|
|
include AdrTestHelpers
|
|
|
|
def adr(id:, title:, status: "Accepted", paths: [], components: [])
|
|
<<~MD
|
|
---
|
|
id: "#{id}"
|
|
date: 2026-07-03
|
|
status: #{status}
|
|
supersedes:
|
|
superseded-by:
|
|
affected-paths: [#{paths.join(', ')}]
|
|
affected-components: [#{components.join(', ')}]
|
|
---
|
|
|
|
# #{id} — #{title}
|
|
|
|
## Context
|
|
|
|
c
|
|
|
|
## Decision
|
|
|
|
d
|
|
|
|
## Consequences
|
|
|
|
q
|
|
|
|
## Alternatives rejected
|
|
|
|
a
|
|
MD
|
|
end
|
|
|
|
def storage_project(&block)
|
|
with_project(
|
|
"0001-storage.md" => adr(id: "0001", title: "Storage", paths: %w[lib/storage db/],
|
|
components: %w[storage]),
|
|
"0002-old-storage.md" => adr(id: "0002", title: "Old storage", status: "Superseded",
|
|
paths: %w[lib/storage]),
|
|
"0003-auth.md" => adr(id: "0003", title: "Auth", paths: %w[lib/auth],
|
|
components: %w[auth]),
|
|
&block
|
|
)
|
|
end
|
|
|
|
def finder(root, graph: nil)
|
|
Adr::Finder.new(repository: Adr::Repository.new(root: root),
|
|
graph_path: graph || File.join(root, "graphify-out", "graph.json"))
|
|
end
|
|
|
|
def test_path_prefix_match_narrows
|
|
storage_project do |root|
|
|
results = finder(root).find(paths: ["lib/storage/adapter.rb"])
|
|
assert_equal ["0001"], results.map { |r| r["id"] }
|
|
assert_equal ["path"], results.first["matched_on"]
|
|
end
|
|
end
|
|
|
|
def test_directory_query_matches_file_scoped_adr
|
|
storage_project do |root|
|
|
results = finder(root).find(paths: ["db"])
|
|
assert_equal ["0001"], results.map { |r| r["id"] }
|
|
end
|
|
end
|
|
|
|
def test_component_match
|
|
storage_project do |root|
|
|
results = finder(root).find(components: ["auth"])
|
|
assert_equal ["0003"], results.map { |r| r["id"] }
|
|
assert_equal ["component"], results.first["matched_on"]
|
|
end
|
|
end
|
|
|
|
def test_accepted_only_by_default_with_override
|
|
storage_project do |root|
|
|
default = finder(root).find(paths: ["lib/storage"])
|
|
assert_equal ["0001"], default.map { |r| r["id"] }
|
|
all = finder(root).find(paths: ["lib/storage"], all_statuses: true)
|
|
assert_equal %w[0001 0002], all.map { |r| r["id"] }.sort
|
|
end
|
|
end
|
|
|
|
def test_no_match_returns_empty
|
|
storage_project do |root|
|
|
assert_empty finder(root).find(paths: ["src/ui"])
|
|
end
|
|
end
|
|
|
|
GRAPH = {
|
|
"nodes" => [
|
|
{ "id" => "n1", "source_file" => "src/api/handler.rb" },
|
|
{ "id" => "n2", "source_file" => "lib/storage/adapter.rb" },
|
|
{ "id" => "n3", "source_file" => "lib/auth/session.rb" }
|
|
],
|
|
"links" => [
|
|
{ "source" => "n1", "target" => "n2" }
|
|
]
|
|
}.freeze
|
|
|
|
def test_graph_layer_expands_one_hop
|
|
storage_project do |root|
|
|
graph_dir = File.join(root, "graphify-out")
|
|
FileUtils.mkdir_p(graph_dir)
|
|
File.write(File.join(graph_dir, "graph.json"), JSON.generate(GRAPH))
|
|
# src/api/handler.rb is in no ADR's affected-paths, but is one hop from
|
|
# lib/storage/adapter.rb which 0001 covers.
|
|
results = finder(root).find(paths: ["src/api/handler.rb"])
|
|
assert_equal ["0001"], results.map { |r| r["id"] }
|
|
assert_equal ["graph"], results.first["matched_on"]
|
|
end
|
|
end
|
|
|
|
def test_degrades_gracefully_without_graph
|
|
storage_project do |root|
|
|
assert_empty finder(root).find(paths: ["src/api/handler.rb"])
|
|
assert_equal ["0001"], finder(root).find(paths: ["lib/storage"]).map { |r| r["id"] }
|
|
end
|
|
end
|
|
|
|
def test_degrades_gracefully_on_corrupt_graph
|
|
storage_project do |root|
|
|
graph_dir = File.join(root, "graphify-out")
|
|
FileUtils.mkdir_p(graph_dir)
|
|
File.write(File.join(graph_dir, "graph.json"), "{not json")
|
|
assert_equal ["0001"], finder(root).find(paths: ["lib/storage"]).map { |r| r["id"] }
|
|
end
|
|
end
|
|
end
|