From c4728dcb952ea2d99a9a64ae0a74335d1f8dea1a Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Mon, 17 Aug 2026 12:51:47 +1200 Subject: [PATCH 1/2] Cover controller layer contracts. Assisted-By: devx/cbdeae41-9308-4071-ad53-58cd92db2946 --- test/utopia/controller/actions.rb | 37 +++++++++++++++++++++++++++++ test/utopia/controller/base.rb | 30 +++++++++++++++++++++++ test/utopia/controller/variables.rb | 6 +++++ 3 files changed, 73 insertions(+) diff --git a/test/utopia/controller/actions.rb b/test/utopia/controller/actions.rb index 591603a7..8514edfc 100644 --- a/test/utopia/controller/actions.rb +++ b/test/utopia/controller/actions.rb @@ -14,6 +14,24 @@ expect(action).to be_equal(action) end + it "compares callbacks and options" do + callback = proc{} + left = subject.new({name: "test"}, &callback) + right = subject.new({name: "test"}, &callback) + + expect(left.eql?(right)).to be == true + expect(left.hash).to be == right.hash + end + + it "describes configured actions" do + callback = proc{} + configured = subject.new({name: "test"}, &callback) + + expect(action.inspect).to be == "" + expect(configured.inspect).to be(:include?, callback.source_location.to_s) + expect(configured.inspect).to be(:include?, '{name: "test"}') + end + it "should resolve callbacks" do specific_action = action.define(["a", "b", "c"]){puts "specific_action"} indirect_action = action.define(["**"]){puts "indirect_action"} @@ -42,3 +60,22 @@ expect(action.matching(["10", "summary", "20"])).to be(:include?, variable_action) end end + +describe Utopia::Controller::Actions do + it "dispatches the fallback action" do + controller_class = Class.new(Utopia::Controller::Base) do + prepend Utopia::Controller::Actions + + otherwise do |request, path| + succeed!(path.to_s) + end + end + + controller = controller_class.new + request = Utopia::Request["GET", "/missing"] + result = controller.process!(request, Utopia::Path["missing"]) + + expect(result).to be_a(Utopia::Controller::Result) + expect(result.value).to be == "missing" + end +end diff --git a/test/utopia/controller/base.rb b/test/utopia/controller/base.rb index f567c0fc..565a1b18 100644 --- a/test/utopia/controller/base.rb +++ b/test/utopia/controller/base.rb @@ -12,6 +12,36 @@ describe Utopia::Controller::Base do let(:controller) {subject.new} + let(:delegate) {Protocol::HTTP::Middleware.for{|request| Utopia::Response.text(request.path.to_s)}} + let(:controller_middleware) {Protocol::HTTP::Middleware.new(delegate)} + let(:controller_class) do + Class.new(subject).tap do |controller_class| + controller_class.const_set(:BASE_PATH, "/tmp/controller") + controller_class.const_set(:URI_PATH, Utopia::Path["/controller"]) + controller_class.const_set(:CONTROLLER, controller_middleware) + end + end + + it "exposes configured controller metadata" do + expect(controller_class.base_path).to be == "/tmp/controller" + expect(controller_class.uri_path).to be == Utopia::Path["/controller"] + expect(controller_class.controller).to be_equal(controller_middleware) + + expect(controller_class.direct?(Utopia::Path["/controller/index"])).to be == true + expect(controller_class.direct?(Utopia::Path["/other/index"])).to be == false + end + + it "delegates requests through its controller middleware" do + request = Utopia::Request["GET", "/controller/index"] + response = controller_class.new.call(request) + + expect(response.status).to be == 200 + expect(response.read).to be == "/controller/index" + end + + it "describes controller instances" do + expect(controller.to_s).to be == "#" + end it "produces semantic results for negotiated responses" do result = controller.catch_response do diff --git a/test/utopia/controller/variables.rb b/test/utopia/controller/variables.rb index ecc2b7ce..39e8d520 100644 --- a/test/utopia/controller/variables.rb +++ b/test/utopia/controller/variables.rb @@ -37,6 +37,12 @@ def copy_instance_variables(from) expect(variables.fetch(:y){:default}).to be == :default end + it "raises when a key is not found" do + expect do + variables.fetch(:missing) + end.to raise_exception(KeyError) + end + it "should convert to hash" do variables << a << b From dc1655e6442d3ec905c0d49c3a6c429917bd423b Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Mon, 17 Aug 2026 12:56:25 +1200 Subject: [PATCH 2/2] Make action inspection test version-independent. Assisted-By: devx/cbdeae41-9308-4071-ad53-58cd92db2946 --- test/utopia/controller/actions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utopia/controller/actions.rb b/test/utopia/controller/actions.rb index 8514edfc..6e7d9683 100644 --- a/test/utopia/controller/actions.rb +++ b/test/utopia/controller/actions.rb @@ -29,7 +29,7 @@ expect(action.inspect).to be == "" expect(configured.inspect).to be(:include?, callback.source_location.to_s) - expect(configured.inspect).to be(:include?, '{name: "test"}') + expect(configured.inspect).to be(:include?, configured.options.inspect) end it "should resolve callbacks" do