Critical fix: defining Opencode::Rails as a module shadowed ::Rails
under Ruby's constant lookup whenever host code referenced top-level
Rails.something from inside the Opencode:: namespace.
Caught when host code in lib/opencode/containers/container.rb failed
to boot:
/workspaces/app/lib/opencode/containers/container.rb:433:
undefined method 'root' for module Opencode::Rails (NoMethodError)
"notes.md" => Rails.root.join(...)
Ruby resolved 'Rails' to 'Opencode::Rails' first (the gem's version
namespace) before falling back to ::Rails. The fix removes the
intermediate module entirely:
module Opencode
RAILS_VERSION = "0.0.1.alpha1"
end
Added a regression test (test_no_opencode_rails_module) so the
shadowing never sneaks back in. opencode-ruby uses Opencode::VERSION
for its own gem version; we can't double-up on that constant, so this
gem uses RAILS_VERSION as a sibling on the same Opencode module.
65 lines
2.5 KiB
Ruby
65 lines
2.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "test_helper"
|
|
|
|
# Smoke test: every constant the gem promises is defined and points at
|
|
# the right kind of object. If require "opencode-rails" loads cleanly,
|
|
# this passes. If the require chain drifts or a file fails to load,
|
|
# this catches it before downstream apps do.
|
|
class Opencode::LoadingTest < Minitest::Test
|
|
GEM_PROVIDED_CONSTANTS = %w[
|
|
Session Turn Exchange Artifact Sandbox SandboxFile
|
|
Transform Impostor MessageArtifacts UploadedFilesPrompt
|
|
ToolDisplay ErrorReporter
|
|
].freeze
|
|
|
|
# Reply / Tracer / Client / etc. ship in opencode-ruby and are
|
|
# transitively required by opencode-rails' umbrella. Verify the
|
|
# require chain pulled them in.
|
|
TRANSITIVE_CONSTANTS_FROM_OPENCODE_RUBY = %w[
|
|
Client Reply ReplyObserver Tracer Prompts
|
|
ResponseParser ToolPart PartSource Todo
|
|
Instrumentation Error
|
|
].freeze
|
|
|
|
def test_gem_provides_expected_constants
|
|
GEM_PROVIDED_CONSTANTS.each do |name|
|
|
assert Opencode.const_defined?(name),
|
|
"Expected Opencode::#{name} to be defined after `require \"opencode-rails\"`"
|
|
end
|
|
end
|
|
|
|
def test_transitively_loads_opencode_ruby_constants
|
|
TRANSITIVE_CONSTANTS_FROM_OPENCODE_RUBY.each do |name|
|
|
assert Opencode.const_defined?(name),
|
|
"Expected Opencode::#{name} to be defined transitively via opencode-ruby"
|
|
end
|
|
end
|
|
|
|
def test_session_constant_points_at_this_gem
|
|
location = Opencode::Session.instance_method(:initialize).source_location.first
|
|
assert_match %r{/opencode-rails/}, location,
|
|
"Expected Opencode::Session to be loaded from opencode-rails, got: #{location}"
|
|
end
|
|
|
|
def test_client_constant_points_at_opencode_ruby
|
|
location = Opencode::Client.instance_method(:initialize).source_location.first
|
|
assert_match %r{/opencode-ruby/}, location,
|
|
"Expected Opencode::Client to come from opencode-ruby, got: #{location}"
|
|
end
|
|
|
|
def test_version_constant
|
|
assert_match(/\A\d+\.\d+\.\d+/, Opencode::RAILS_VERSION)
|
|
end
|
|
|
|
def test_no_opencode_rails_module
|
|
# Defining Opencode::Rails as a module would shadow ::Rails for any
|
|
# host code that references top-level Rails.* from inside the
|
|
# Opencode:: namespace (e.g. lib/opencode/containers/container.rb).
|
|
# Verify the namespace stays clean — version lives at
|
|
# Opencode::RAILS_VERSION, not Opencode::Rails::VERSION.
|
|
refute Opencode.const_defined?(:Rails),
|
|
"Opencode::Rails must not be defined — it would shadow ::Rails inside the Opencode namespace"
|
|
end
|
|
end
|