admin: silence phlex's warnings at require time
Replaces 3b716c88's Warning.warn filter, which worked but was heavier
than the job asked for.
Assisted-by: GLM-5.3 via pi
diff --git a/lib/pro_tacts/admin/contacts_index.rb b/lib/pro_tacts/admin/contacts_index.rb
index 6e24a8a..93ecf32 100644
--- a/lib/pro_tacts/admin/contacts_index.rb
+++ b/lib/pro_tacts/admin/contacts_index.rb
@@ -1,4 +1,4 @@
-require "phlex"
+require "pro_tacts/admin/phlex"
require "pro_tacts/admin/format"
require "pro_tacts/admin/layout"
diff --git a/lib/pro_tacts/admin/contacts_show.rb b/lib/pro_tacts/admin/contacts_show.rb
index 5c38654..b67dedb 100644
--- a/lib/pro_tacts/admin/contacts_show.rb
+++ b/lib/pro_tacts/admin/contacts_show.rb
@@ -1,4 +1,4 @@
-require "phlex"
+require "pro_tacts/admin/phlex"
require "pro_tacts/admin/format"
require "pro_tacts/admin/layout"
diff --git a/lib/pro_tacts/admin/layout.rb b/lib/pro_tacts/admin/layout.rb
index 85aaf21..29e6405 100644
--- a/lib/pro_tacts/admin/layout.rb
+++ b/lib/pro_tacts/admin/layout.rb
@@ -1,4 +1,4 @@
-require "phlex"
+require "pro_tacts/admin/phlex"
module ProTacts
module Admin
diff --git a/lib/pro_tacts/admin/phlex.rb b/lib/pro_tacts/admin/phlex.rb
new file mode 100644
index 0000000..387c04f
--- /dev/null
+++ b/lib/pro_tacts/admin/phlex.rb
@@ -0,0 +1,27 @@
+require "pro_tacts/warnings"
+
+# The admin's phlex require. Phlex lazy-loads: `require "phlex"`
+# registers autoloads and the files that warn -- a page of
+# mismatched-indentation and method-redefined warnings under `ruby
+# -w`, which the test task runs -- compile only when Phlex::HTML is
+# first referenced, by then outside any block. So this loads phlex's
+# own files eagerly inside the silence; the views require this file
+# instead of phlex, and every later require or autoload hit is a
+# no-op. sgml/state is in the set because it loads later still, at
+# the first render, and carries its own warning.
+ProTacts.silence_warnings do
+ require "phlex"
+ require "phlex/html"
+ require "phlex/sgml/state"
+
+ # Two warnings survive the requires: sgml.rb passes &block to
+ # before_template and after_template, methods that ignore it, and
+ # Ruby warns once per process at the first render carrying a
+ # content block -- the render(Layout.new) { ... } shape every
+ # screen here uses. Spending that first render now, on a throwaway
+ # component whose output is discarded, means no later one warns.
+ inner = Class.new(Phlex::HTML) { def view_template; h1 { "warm" }; end }
+ Class.new(Phlex::HTML) do
+ define_method(:view_template) { render inner.new { nil } }
+ end.new.call
+end
diff --git a/lib/pro_tacts/admin/upcoming_birthdays.rb b/lib/pro_tacts/admin/upcoming_birthdays.rb
index 4a7ecc8..8343f6e 100644
--- a/lib/pro_tacts/admin/upcoming_birthdays.rb
+++ b/lib/pro_tacts/admin/upcoming_birthdays.rb
@@ -1,4 +1,4 @@
-require "phlex"
+require "pro_tacts/admin/phlex"
require "pro_tacts/admin/format"
diff --git a/lib/pro_tacts/warnings.rb b/lib/pro_tacts/warnings.rb
new file mode 100644
index 0000000..c0463cb
--- /dev/null
+++ b/lib/pro_tacts/warnings.rb
@@ -0,0 +1,17 @@
+module ProTacts
+ # Turns the interpreter's warnings off for the block and restores
+ # them after -- including on raise -- so code that is noisy under
+ # -w can run quietly without silencing anything else. $VERBOSE is
+ # the global switch the interpreter reads, not a thread-local one,
+ # so this belongs at boot-time requires and not on request paths.
+ # Used to require phlex, whose files warn by the page (see
+ # admin/phlex.rb).
+ #: [T] () { () -> T } -> T
+ def self.silence_warnings
+ verbose = $VERBOSE
+ $VERBOSE = nil
+ yield
+ ensure
+ $VERBOSE = verbose
+ end
+end
diff --git a/test/pro_tacts/test_warnings.rb b/test/pro_tacts/test_warnings.rb
new file mode 100644
index 0000000..e769baa
--- /dev/null
+++ b/test/pro_tacts/test_warnings.rb
@@ -0,0 +1,21 @@
+require_relative "../test_helper"
+
+# ProTacts.silence_warnings, the block helper behind the quiet phlex
+# requires: warnings off inside, back on after — including when the
+# block raises, which is the half a missing ensure would get wrong
+# only when something has already failed.
+class ProTactsWarningsTest < Minitest::Test
+ def test_silences_warnings_for_the_block_and_restores_them_after
+ verbose = $VERBOSE
+ ProTacts.silence_warnings { assert_nil $VERBOSE }
+ assert_equal verbose, $VERBOSE
+ end
+
+ def test_restores_warnings_when_the_block_raises
+ verbose = $VERBOSE
+
+ assert_raises(RuntimeError) { ProTacts.silence_warnings { raise "boom" } }
+
+ assert_equal verbose, $VERBOSE
+ end
+end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 236c589..29cb674 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -42,35 +42,6 @@ Minitest.after_run { FileUtils.rm_rf(unhandled_dir) }
ENV["PRO_TACTS_DEBUG_LOG"] ||= "log/test.log"
File.truncate("log/test.log", 0) if File.exist?("log/test.log")
-# The interpreter runs with -w (the test task's flag), and phlex's own
-# files compile under it into a stream of warnings — mismatched
-# indentations, a method-redefined pair for every void element — none
-# of it app code. Suppressed here, path-scoped to the gem's install
-# directory rather than globally, so this suite's own warnings (an
-# ambiguous `/` in test_store.rb, say) still surface. Defined after the
-# ENV block but before the first require that loads phlex: the spec
-# lookup finds the path without requiring the gem, and the override is
-# in place before phlex's files ever compile. Nothing later in this
-# file or the suite re-overrides Warning.warn, so the chain holds.
-module PhlexWarningFilter
- PHLEX_PATH = Gem::Specification.find_by_name("phlex").full_gem_path
-
- #: (String message) -> bool
- def self.from_phlex?(message)
- message.start_with?("#{PHLEX_PATH}/")
- end
-end
-
-module Warning
- class << self
- alias_method :warn_without_phlex_filter, :warn
- end
-
- def self.warn(message, **kwargs)
- warn_without_phlex_filter(message, **kwargs) unless PhlexWarningFilter.from_phlex?(message)
- end
-end
-
require_relative "fixture_data"
require "pro_tacts/web"
require "minitest/autorun"
diff --git a/test/test_phlex_warning_filter.rb b/test/test_phlex_warning_filter.rb
deleted file mode 100644
index 9276959..0000000
--- a/test/test_phlex_warning_filter.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-require_relative "test_helper"
-
-# The path predicate behind the Warning.warn override in test_helper:
-# phlex's install directory and nothing else. The trailing slash in the
-# comparison is what keeps a hypothetical neighboring gem (a phlex-foo,
-# installed beside phlex) from matching on prefix alone. The override's
-# wiring is not asserted here — calling Warning.warn from a test would
-# print the very warnings this suite suppresses — so the wiring is
-# verified by the test run's own output instead.
-class PhlexWarningFilterTest < Minitest::Test
- def test_matches_only_messages_from_phlex_install_path
- phlex = "#{PhlexWarningFilter::PHLEX_PATH}/lib/phlex/html.rb:84: " \
- "warning: mismatched indentations at 'elsif' with 'if' at 58"
- assert PhlexWarningFilter.from_phlex?(phlex)
-
- app = "test/pro_tacts/test_store.rb:626: warning: ambiguous `/`"
- refute PhlexWarningFilter.from_phlex?(app)
- end
-end