admin_suite 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -0
  3. data/CHANGELOG.md +69 -11
  4. data/CONTRIBUTING.md +9 -4
  5. data/README.md +21 -5
  6. data/app/controllers/admin_suite/application_controller.rb +12 -11
  7. data/app/controllers/admin_suite/mcp_controller.rb +36 -0
  8. data/app/controllers/admin_suite/resources_controller.rb +7 -78
  9. data/app/views/admin_suite/resources/index.html.erb +1 -0
  10. data/config/routes.rb +5 -0
  11. data/lib/admin/base/resource.rb +7 -29
  12. data/lib/admin_suite/auth/host_user.rb +42 -0
  13. data/lib/admin_suite/auth/strategy.rb +1 -1
  14. data/lib/admin_suite/auth.rb +15 -0
  15. data/lib/admin_suite/authorization_context.rb +28 -0
  16. data/lib/admin_suite/configuration.rb +56 -2
  17. data/lib/admin_suite/mcp/authorization.rb +68 -0
  18. data/lib/admin_suite/mcp/serializer.rb +138 -0
  19. data/lib/admin_suite/mcp/tools/aggregate.rb +55 -0
  20. data/lib/admin_suite/mcp/tools/describe_resources.rb +63 -0
  21. data/lib/admin_suite/mcp/tools/get_record.rb +41 -0
  22. data/lib/admin_suite/mcp/tools/list_records.rb +67 -0
  23. data/lib/admin_suite/mcp.rb +53 -0
  24. data/lib/admin_suite/query.rb +71 -0
  25. data/lib/admin_suite/ui/show_value_formatter.rb +2 -2
  26. data/lib/admin_suite/version.rb +1 -1
  27. data/lib/admin_suite.rb +14 -9
  28. data/lib/generators/admin_suite/install/templates/admin_suite.rb +5 -2
  29. data/test/controllers/resources_controller_test.rb +19 -13
  30. data/test/integration/authentication_test.rb +10 -0
  31. data/test/integration/authorization_test.rb +20 -3
  32. data/test/integration/index_query_characterization_test.rb +229 -0
  33. data/test/integration/mcp_aggregate_test.rb +44 -0
  34. data/test/integration/mcp_authorization_test.rb +102 -0
  35. data/test/integration/mcp_endpoint_test.rb +89 -0
  36. data/test/integration/mcp_get_record_test.rb +62 -0
  37. data/test/integration/mcp_instrumentation_test.rb +107 -0
  38. data/test/integration/mcp_list_records_test.rb +75 -0
  39. data/test/integration/mcp_parity_test.rb +155 -0
  40. data/test/integration/mcp_release_test.rb +131 -0
  41. data/test/integration/read_only_resource_test.rb +128 -2
  42. data/test/integration/searchable_select_search_test.rb +5 -4
  43. data/test/lib/auth_host_user_test.rb +52 -0
  44. data/test/lib/auth_http_basic_test.rb +10 -0
  45. data/test/lib/auth_test.rb +20 -3
  46. data/test/lib/authorization_context_test.rb +127 -0
  47. data/test/lib/engine_defaults_test.rb +1 -2
  48. data/test/lib/mcp_serializer_test.rb +107 -0
  49. data/test/lib/query_test.rb +91 -0
  50. data/test/lib/removed_deprecations_test.rb +16 -0
  51. data/test/publish_workflow_test.rb +63 -0
  52. data/test/test_helper.rb +26 -0
  53. metadata +42 -5
  54. data/lib/admin_suite/renderers/legacy_gleania.rb +0 -232
  55. data/test/lib/legacy_renderer_deprecation_test.rb +0 -42
  56. data/test/lib/resource_exportable_deprecation_test.rb +0 -47
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: admin_suite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - TechWright Labs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-01 00:00:00.000000000 Z
11
+ date: 2026-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -50,6 +50,20 @@ dependencies:
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
52
  version: '10'
53
+ - !ruby/object:Gem::Dependency
54
+ name: mcp
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '1.1'
60
+ type: :runtime
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '1.1'
53
67
  - !ruby/object:Gem::Dependency
54
68
  name: turbo-rails
55
69
  requirement: !ruby/object:Gem::Requirement
@@ -152,6 +166,7 @@ files:
152
166
  - app/controllers/admin_suite/application_controller.rb
153
167
  - app/controllers/admin_suite/dashboard_controller.rb
154
168
  - app/controllers/admin_suite/docs_controller.rb
169
+ - app/controllers/admin_suite/mcp_controller.rb
155
170
  - app/controllers/admin_suite/portals_controller.rb
156
171
  - app/controllers/admin_suite/resources_controller.rb
157
172
  - app/helpers/admin_suite/base_helper.rb
@@ -205,8 +220,10 @@ files:
205
220
  - lib/admin_suite.rb
206
221
  - lib/admin_suite/auth.rb
207
222
  - lib/admin_suite/auth/host_hook.rb
223
+ - lib/admin_suite/auth/host_user.rb
208
224
  - lib/admin_suite/auth/http_basic.rb
209
225
  - lib/admin_suite/auth/strategy.rb
226
+ - lib/admin_suite/authorization_context.rb
210
227
  - lib/admin_suite/configuration.rb
211
228
  - lib/admin_suite/definition_loader.rb
212
229
  - lib/admin_suite/deprecation.rb
@@ -214,14 +231,21 @@ files:
214
231
  - lib/admin_suite/host_autoload_policy.rb
215
232
  - lib/admin_suite/legacy_custom_renderer_procs.rb
216
233
  - lib/admin_suite/markdown_renderer.rb
234
+ - lib/admin_suite/mcp.rb
235
+ - lib/admin_suite/mcp/authorization.rb
236
+ - lib/admin_suite/mcp/serializer.rb
237
+ - lib/admin_suite/mcp/tools/aggregate.rb
238
+ - lib/admin_suite/mcp/tools/describe_resources.rb
239
+ - lib/admin_suite/mcp/tools/get_record.rb
240
+ - lib/admin_suite/mcp/tools/list_records.rb
217
241
  - lib/admin_suite/portal_definition.rb
218
242
  - lib/admin_suite/portal_registry.rb
243
+ - lib/admin_suite/query.rb
219
244
  - lib/admin_suite/renderer.rb
220
245
  - lib/admin_suite/renderer_registry.rb
221
246
  - lib/admin_suite/renderers/code_renderer.rb
222
247
  - lib/admin_suite/renderers/json_renderer.rb
223
248
  - lib/admin_suite/renderers/key_value_renderer.rb
224
- - lib/admin_suite/renderers/legacy_gleania.rb
225
249
  - lib/admin_suite/renderers/table_from_renderer.rb
226
250
  - lib/admin_suite/section_definition.rb
227
251
  - lib/admin_suite/theme_palette.rb
@@ -288,8 +312,17 @@ files:
288
312
  - test/integration/chart_panel_test.rb
289
313
  - test/integration/dashboard_test.rb
290
314
  - test/integration/docs_test.rb
315
+ - test/integration/index_query_characterization_test.rb
291
316
  - test/integration/index_table_test.rb
292
317
  - test/integration/layout_assets_test.rb
318
+ - test/integration/mcp_aggregate_test.rb
319
+ - test/integration/mcp_authorization_test.rb
320
+ - test/integration/mcp_endpoint_test.rb
321
+ - test/integration/mcp_get_record_test.rb
322
+ - test/integration/mcp_instrumentation_test.rb
323
+ - test/integration/mcp_list_records_test.rb
324
+ - test/integration/mcp_parity_test.rb
325
+ - test/integration/mcp_release_test.rb
293
326
  - test/integration/navigation_sections_test.rb
294
327
  - test/integration/pagination_and_stats_test.rb
295
328
  - test/integration/read_only_resource_test.rb
@@ -299,23 +332,27 @@ files:
299
332
  - test/integration/toggle_test.rb
300
333
  - test/lib/action_executor_redirect_test.rb
301
334
  - test/lib/action_executor_test.rb
335
+ - test/lib/auth_host_user_test.rb
302
336
  - test/lib/auth_http_basic_test.rb
303
337
  - test/lib/auth_resolution_test.rb
304
338
  - test/lib/auth_test.rb
339
+ - test/lib/authorization_context_test.rb
305
340
  - test/lib/builtin_renderers_test.rb
306
341
  - test/lib/definition_loader_test.rb
307
342
  - test/lib/engine_defaults_test.rb
308
343
  - test/lib/form_field_renderer_test.rb
309
344
  - test/lib/format_table_cell_test.rb
310
345
  - test/lib/index_includes_test.rb
311
- - test/lib/legacy_renderer_deprecation_test.rb
312
346
  - test/lib/markdown_renderer_test.rb
347
+ - test/lib/mcp_serializer_test.rb
348
+ - test/lib/query_test.rb
349
+ - test/lib/removed_deprecations_test.rb
313
350
  - test/lib/renderer_test.rb
314
- - test/lib/resource_exportable_deprecation_test.rb
315
351
  - test/lib/resource_observability_extensions_test.rb
316
352
  - test/lib/show_value_formatter_test.rb
317
353
  - test/lib/theme_palette_test.rb
318
354
  - test/lib/zeitwerk_integration_test.rb
355
+ - test/publish_workflow_test.rb
319
356
  - test/test_helper.rb
320
357
  homepage: https://github.com/techwright-lab/admin_suite
321
358
  licenses:
@@ -1,232 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AdminSuite
4
- module Renderers
5
- # The four Gleania-specific LLM chat-transcript renderers, moved verbatim
6
- # out of `AdminSuite::BaseHelper` (role-coloured message bubbles, tool-call
7
- # panels, prompt-template mustache highlighting).
8
- #
9
- # These are deprecated: they still work in 0.4.0 (logging a warning once
10
- # per key per process the first time each is used), and are targeted for
11
- # DELETION in 0.6.0 (moved from the originally-planned 0.5.0/Phase 2b,
12
- # pending both the gleania and trust_growth host migrations). Gleania is
13
- # expected to migrate to host-side renderer classes under
14
- # `app/admin/renderers/*.rb` before then.
15
- #
16
- # The renderer bodies below are intentionally byte-equivalent to the
17
- # BaseHelper methods they replace, other than `resource` -> `record` and
18
- # routing BaseHelper method calls (`render_json_block`, `simple_format`,
19
- # `concat`) through `view.` — this class is not `included` into the view,
20
- # so those calls can't resolve as bare method sends the way they did
21
- # inside the helper module. Do not "improve" this markup: a byte-for-byte
22
- # move keeps gleania's Assistant/AI portal pages pixel-identical, and
23
- # makes the eventual 0.6.0 deletion a clean removal.
24
- module LegacyGleania
25
- extend AdminSuite::Deprecation
26
-
27
- DEPRECATION_MESSAGE_FORMAT =
28
- "AdminSuite: the :%<key>s renderer is deprecated and will be removed in 0.6.0. " \
29
- "Move it to app/admin/renderers in your app."
30
-
31
- class << self
32
- # Fires the deprecation sink at most once per `key` per process.
33
- # `warn_once_sink` and `reset_deprecation_notices!` come from
34
- # `AdminSuite::Deprecation`, extended above.
35
- #
36
- # @param key [Symbol]
37
- # @return [void]
38
- def warn_once(key)
39
- super(key, format(DEPRECATION_MESSAGE_FORMAT, key: key))
40
- end
41
- end
42
-
43
- # Verbatim from `BaseHelper#render_prompt_template`.
44
- class PromptTemplateRenderer < Renderer
45
- def render
46
- LegacyGleania.warn_once(:prompt_template_preview)
47
-
48
- template = record.respond_to?(:prompt_template) ? record.prompt_template : nil
49
- return content_tag(:p, "No template defined", class: "text-slate-500 italic") if template.blank?
50
-
51
- highlighted_template = h(template).gsub(/\{\{(\w+)\}\}/) do
52
- "<span class=\"text-amber-400 bg-amber-900/30 px-1 rounded\">{{#{$1}}}</span>"
53
- end
54
-
55
- content_tag(:div, class: "relative group") do
56
- view.concat(content_tag(:div, class: "absolute top-2 right-2 flex items-center gap-2") do
57
- view.concat(content_tag(:span, "TEMPLATE", class: "text-xs font-medium text-slate-400 uppercase tracking-wider"))
58
- view.concat(content_tag(:button,
59
- '<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/></svg>'.html_safe,
60
- type: "button",
61
- class: "p-1 text-slate-400 hover:text-slate-600 opacity-0 group-hover:opacity-100 transition-opacity",
62
- data: { controller: "admin-suite--clipboard", action: "click->admin-suite--clipboard#copy", "admin-suite--clipboard-text-value": template },
63
- title: "Copy to clipboard"))
64
- end)
65
-
66
- view.concat(content_tag(:pre, class: "bg-slate-900 text-slate-100 p-4 rounded-lg overflow-x-auto text-sm font-mono max-h-[600px] overflow-y-auto whitespace-pre-wrap leading-relaxed") do
67
- highlighted_template.html_safe
68
- end)
69
-
70
- variables = template.scan(/\{\{(\w+)\}\}/).flatten.uniq
71
- if variables.any?
72
- view.concat(content_tag(:div, class: "mt-3 pt-3 border-t border-slate-700") do
73
- view.concat(content_tag(:span, "Variables: ", class: "text-sm text-slate-400"))
74
- view.concat(content_tag(:div, class: "inline-flex flex-wrap gap-1 mt-1") do
75
- variables.each do |var|
76
- view.concat(content_tag(:code, "{{#{var}}}", class: "text-xs px-2 py-0.5 bg-amber-900/30 text-amber-400 rounded"))
77
- end
78
- end)
79
- end)
80
- end
81
- end
82
- end
83
- end
84
-
85
- # Verbatim from `BaseHelper#render_messages_preview`.
86
- class MessagesPreviewRenderer < Renderer
87
- def render
88
- LegacyGleania.warn_once(:messages_preview)
89
-
90
- messages = record.respond_to?(:messages) ? record.messages : []
91
- if messages.respond_to?(:chronological)
92
- messages = messages.chronological
93
- end
94
- messages = messages.limit(50) if messages.respond_to?(:limit)
95
- messages = Array.wrap(messages)
96
-
97
- return content_tag(:p, "No messages", class: "text-slate-500 italic") if messages.blank?
98
-
99
- content_tag(:div, class: "space-y-4 max-h-[600px] overflow-y-auto -mx-6 -mb-6 p-6 pt-0") do
100
- messages.each_with_index do |msg, idx|
101
- if msg.respond_to?(:role)
102
- role = msg.role
103
- content = msg.content
104
- created_at = msg.respond_to?(:created_at) ? msg.created_at : nil
105
- else
106
- role = msg["role"] || msg[:role] || "unknown"
107
- content = msg["content"] || msg[:content] || ""
108
- created_at = msg["created_at"] || msg[:created_at]
109
- end
110
-
111
- role_class = case role.to_s
112
- when "user" then "bg-blue-50 border-blue-200"
113
- when "assistant" then "bg-emerald-50 border-emerald-200"
114
- when "tool" then "bg-amber-50 border-amber-200"
115
- when "system" then "bg-slate-50 border-slate-200"
116
- else "bg-slate-50 border-slate-200"
117
- end
118
-
119
- role_icon = case role.to_s
120
- when "user"
121
- '<svg class="w-4 h-4 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg>'.html_safe
122
- when "assistant"
123
- '<svg class="w-4 h-4 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"/></svg>'.html_safe
124
- when "tool"
125
- '<svg class="w-4 h-4 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/></svg>'.html_safe
126
- else
127
- '<svg class="w-4 h-4 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"/></svg>'.html_safe
128
- end
129
-
130
- view.concat(content_tag(:div, class: "rounded-lg border p-4 #{role_class}") do
131
- view.concat(content_tag(:div, class: "flex items-center justify-between mb-3") do
132
- view.concat(content_tag(:div, class: "flex items-center gap-2") do
133
- view.concat(role_icon)
134
- view.concat(content_tag(:span, role.to_s.capitalize, class: "text-sm font-medium text-slate-700"))
135
- end)
136
- view.concat(content_tag(:div, class: "flex items-center gap-2 text-xs text-slate-400") do
137
- view.concat(content_tag(:span, created_at.strftime("%H:%M:%S"))) if created_at.respond_to?(:strftime)
138
- view.concat(content_tag(:span, "##{idx + 1}"))
139
- end)
140
- end)
141
-
142
- content_str = content.to_s
143
- if role.to_s == "tool" && content_str.start_with?("{", "[")
144
- begin
145
- parsed = JSON.parse(content_str)
146
- view.concat(view.render_json_block(parsed))
147
- rescue JSON::ParserError
148
- view.concat(content_tag(:div, view.simple_format(h(content_str)), class: "prose prose-sm max-w-none"))
149
- end
150
- else
151
- view.concat(content_tag(:div, view.simple_format(h(content_str)), class: "prose prose-sm max-w-none"))
152
- end
153
- end)
154
- end
155
- end
156
- end
157
- end
158
-
159
- # Verbatim from `BaseHelper#render_tool_args_preview`.
160
- class ToolArgsRenderer < Renderer
161
- def render
162
- LegacyGleania.warn_once(:tool_args_preview)
163
-
164
- args = record.respond_to?(:args) ? record.args : (record.respond_to?(:arguments) ? record.arguments : {})
165
- result = record.respond_to?(:result) ? record.result : nil
166
- error = record.respond_to?(:error) ? record.error : nil
167
-
168
- content_tag(:div, class: "space-y-6") do
169
- view.concat(content_tag(:div) do
170
- view.concat(content_tag(:h4, "Arguments", class: "text-sm font-medium text-slate-500 mb-2"))
171
- if args.present? && args != {}
172
- view.concat(view.render_json_block(args))
173
- else
174
- view.concat(content_tag(:p, "No arguments", class: "text-slate-400 italic text-sm"))
175
- end
176
- end)
177
-
178
- if result.present? && result != {}
179
- view.concat(content_tag(:div, class: "pt-4 border-t border-slate-200") do
180
- view.concat(content_tag(:h4, "Result", class: "text-sm font-medium text-slate-500 mb-2"))
181
- view.concat(view.render_json_block(result))
182
- end)
183
- end
184
-
185
- if error.present?
186
- view.concat(content_tag(:div, class: "pt-4 border-t border-slate-200") do
187
- view.concat(content_tag(:h4, "Error", class: "text-sm font-medium text-red-500 mb-2"))
188
- view.concat(content_tag(:div, class: "bg-red-50 border border-red-200 rounded-lg p-4") do
189
- content_tag(:pre, h(error.to_s), class: "text-sm text-red-700 whitespace-pre-wrap font-mono")
190
- end)
191
- end)
192
- end
193
- end
194
- end
195
- end
196
-
197
- # Verbatim from `BaseHelper#render_turn_messages_preview`.
198
- class TurnMessagesRenderer < Renderer
199
- def render
200
- LegacyGleania.warn_once(:turn_messages_preview)
201
-
202
- user_msg = record.respond_to?(:user_message) ? record.user_message : nil
203
- asst_msg = record.respond_to?(:assistant_message) ? record.assistant_message : nil
204
-
205
- content_tag(:div, class: "space-y-4") do
206
- if user_msg
207
- view.concat(content_tag(:div, class: "rounded-lg border p-4 bg-blue-50 border-blue-200") do
208
- view.concat(content_tag(:div, class: "flex items-center gap-2 mb-2") do
209
- view.concat('<svg class="w-4 h-4 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg>'.html_safe)
210
- view.concat(content_tag(:span, "User", class: "text-sm font-medium text-slate-700"))
211
- end)
212
- view.concat(content_tag(:div, view.simple_format(h(user_msg.respond_to?(:content) ? user_msg.content.to_s : user_msg.to_s)), class: "prose prose-sm max-w-none"))
213
- end)
214
- end
215
-
216
- if asst_msg
217
- view.concat(content_tag(:div, class: "rounded-lg border p-4 bg-emerald-50 border-emerald-200") do
218
- view.concat(content_tag(:div, class: "flex items-center gap-2 mb-2") do
219
- view.concat('<svg class="w-4 h-4 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"/></svg>'.html_safe)
220
- view.concat(content_tag(:span, "Assistant", class: "text-sm font-medium text-slate-700"))
221
- end)
222
- view.concat(content_tag(:div, view.simple_format(h(asst_msg.respond_to?(:content) ? asst_msg.content.to_s : asst_msg.to_s)), class: "prose prose-sm max-w-none"))
223
- end)
224
- end
225
-
226
- view.concat(content_tag(:p, "No messages found", class: "text-slate-400 italic text-sm")) unless user_msg || asst_msg
227
- end
228
- end
229
- end
230
- end
231
- end
232
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "test_helper"
4
-
5
- module AdminSuite
6
- class LegacyRendererDeprecationTest < ActionView::TestCase
7
- include ::ERB::Util
8
- include AdminSuite::BaseHelper
9
-
10
- Prompt = Struct.new(:prompt_template)
11
-
12
- setup { AdminSuite::Renderers::LegacyGleania.reset_deprecation_notices! }
13
-
14
- test "the legacy prompt renderer still renders its template" do
15
- html = render_custom_section(Prompt.new("Hello {{name}}"), :prompt_template_preview)
16
- assert_includes html, "Hello"
17
- assert_includes html, "name"
18
- end
19
-
20
- test "using a legacy renderer logs a deprecation once per key" do
21
- logged = []
22
- AdminSuite::Renderers::LegacyGleania.stub(:warn_once_sink, ->(msg) { logged << msg }) do
23
- 2.times { render_custom_section(Prompt.new("x"), :prompt_template_preview) }
24
- end
25
- assert_equal 1, logged.size
26
- assert_includes logged.first, "deprecated"
27
- # Deliberately a hardcoded literal, not read off
28
- # DEPRECATION_MESSAGE_FORMAT: reading the version out of the constant
29
- # under test and asserting the message contains it is true by
30
- # construction (format() only substitutes %<key>s, never the version
31
- # digits), so it can never fail on a wrong retarget -- exactly the
32
- # property this test exists to catch. If the removal target changes
33
- # again, this literal must be updated by hand; that's the point.
34
- assert_includes logged.first, "0.6.0"
35
- end
36
-
37
- test "the gem no longer includes the host CustomRenderersHelper constant" do
38
- source = AdminSuite::Engine.root.join("app/helpers/admin_suite/base_helper.rb").read
39
- refute_includes source, "Internal::Developer::CustomRenderersHelper"
40
- end
41
- end
42
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "test_helper"
4
-
5
- module AdminSuite
6
- class ResourceExportableDeprecationTest < ActiveSupport::TestCase
7
- # Regression fixture for Finding 1 of the whole-branch review: Task 8
8
- # removed `exportable` after grepping the *gem* for readers, but host
9
- # apps are *callers* of this DSL (gleania: 30 resource files;
10
- # trust_growth: 1). A real removal raises `NoMethodError` at
11
- # definition-load time -- and in production `DefinitionLoader` logs and
12
- # swallows that, so the resource silently vanishes from the admin.
13
- class LegacyExportableResource < Admin::Base::Resource
14
- exportable :json, :csv
15
- end
16
-
17
- setup { LegacyExportableResource.reset_deprecation_notices! }
18
-
19
- test "calling exportable in a resource body is harmless" do
20
- assert_nothing_raised { LegacyExportableResource.exportable(:json, :csv) }
21
- end
22
-
23
- test "exportable does not restore any export-format reader" do
24
- refute LegacyExportableResource.respond_to?(:export_formats)
25
- refute LegacyExportableResource.instance_variable_defined?(:@export_formats)
26
- end
27
-
28
- test "exportable warns once per resource class, naming the class and the 0.6.0 removal" do
29
- logged = []
30
- LegacyExportableResource.stub(:warn_once_sink, ->(msg) { logged << msg }) do
31
- 2.times { LegacyExportableResource.exportable(:json, :csv) }
32
- end
33
-
34
- assert_equal 1, logged.size
35
- assert_includes logged.first, "LegacyExportableResource"
36
- # Deliberately a hardcoded literal, not read off
37
- # EXPORTABLE_DEPRECATION_MESSAGE_FORMAT: reading the version out of
38
- # the constant under test and asserting the message contains it is
39
- # true by construction (format() only substitutes %<resource>s, never
40
- # the version digits), so it can never fail on a wrong retarget --
41
- # exactly the property this test exists to catch. If the removal
42
- # target changes again, this literal must be updated by hand; that's
43
- # the point.
44
- assert_includes logged.first, "0.6.0"
45
- end
46
- end
47
- end