torikago 0.0.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.
@@ -0,0 +1,549 @@
1
+ require_relative "../test_helper"
2
+ require "fileutils"
3
+ require "open3"
4
+ require "rbconfig"
5
+ require "tmpdir"
6
+
7
+ class TorikagoEngineContainerTest < Minitest::Test
8
+ def teardown
9
+ Object.send(:remove_const, :Foo) if Object.const_defined?(:Foo, false)
10
+ Object.send(:remove_const, :SharedDependency) if Object.const_defined?(:SharedDependency, false)
11
+ Object.send(:remove_const, :SetupProbe) if Object.const_defined?(:SetupProbe, false)
12
+ Object.send(:remove_const, :VersionedFormatter) if Object.const_defined?(:VersionedFormatter, false)
13
+ end
14
+
15
+ def test_call_loads_the_public_api_class_and_executes_call
16
+ with_module_root do |module_root|
17
+ container = Torikago::EngineContainer.new(name: :foo, module_root: module_root)
18
+
19
+ result = container.call("Foo::ListProductsQuery")
20
+
21
+ assert_equal ["coffee-beans", "drip-bag"], result
22
+ end
23
+ end
24
+
25
+ def test_call_reuses_loaded_runtime_files_across_calls
26
+ with_module_root do |module_root|
27
+ container = Torikago::EngineContainer.new(name: :foo, module_root: module_root)
28
+
29
+ first = container.call("Foo::ListProductsQuery")
30
+ second = container.call("Foo::ListProductsQuery")
31
+
32
+ assert_equal ["coffee-beans", "drip-bag"], first
33
+ assert_equal ["coffee-beans", "drip-bag"], second
34
+ end
35
+ end
36
+
37
+ def test_call_sets_the_current_box_during_execution
38
+ with_module_root do |module_root|
39
+ container = Torikago::EngineContainer.new(name: :foo, module_root: module_root)
40
+
41
+ result = container.call("Foo::CurrentBoxQuery")
42
+
43
+ assert_equal :foo, result
44
+ assert_nil Torikago::CurrentExecution.current_box
45
+ end
46
+ end
47
+
48
+ def test_call_uses_a_configured_entrypoint_directory_when_present
49
+ with_custom_entrypoint_module_root do |module_root|
50
+ container = Torikago::EngineContainer.new(
51
+ name: :foo,
52
+ module_root: module_root,
53
+ entrypoint: "components/public_api"
54
+ )
55
+
56
+ result = container.call("Foo::CustomEntryPointQuery")
57
+
58
+ assert_equal "custom entrypoint", result
59
+ end
60
+ end
61
+
62
+ def test_call_does_not_load_parent_files_when_configured_entrypoint_directory_is_missing
63
+ Dir.mktmpdir("torikago-engine-container") do |module_root|
64
+ FileUtils.mkdir_p(File.join(module_root, "app/controllers/foo"))
65
+ File.write(
66
+ File.join(module_root, "app/controllers/foo/widgets_controller.rb"),
67
+ <<~RUBY
68
+ raise "app/controllers should not be loaded as public API"
69
+ RUBY
70
+ )
71
+
72
+ container = Torikago::EngineContainer.new(
73
+ name: :foo,
74
+ module_root: module_root,
75
+ entrypoint: "app/package_api"
76
+ )
77
+
78
+ error = assert_raises(NameError) do
79
+ container.call("Foo::MissingQuery")
80
+ end
81
+
82
+ assert_match(/MissingQuery/, error.message)
83
+ end
84
+ end
85
+
86
+ def test_call_prepends_explicit_gemfile_require_paths_before_loading_runtime
87
+ with_module_root do |module_root|
88
+ dependency_lib = File.join(module_root, "vendor/example-gem-1.2.3/lib")
89
+ FileUtils.mkdir_p(dependency_lib)
90
+ File.write(
91
+ File.join(dependency_lib, "shared_dependency.rb"),
92
+ <<~RUBY
93
+ module SharedDependency
94
+ VERSION = "module-local"
95
+ end
96
+ RUBY
97
+ )
98
+ File.write(File.join(module_root, "Gemfile"), "")
99
+ File.write(
100
+ File.join(module_root, "app/package_api/foo/dependency_version_query.rb"),
101
+ <<~RUBY
102
+ require "shared_dependency"
103
+
104
+ class Foo::DependencyVersionQuery
105
+ def call
106
+ SharedDependency::VERSION
107
+ end
108
+ end
109
+ RUBY
110
+ )
111
+
112
+ assert_ruby_box_child_process(
113
+ <<~RUBY,
114
+ $LOAD_PATH.unshift(ARGV.fetch(0))
115
+ module_root = ARGV.fetch(1)
116
+ dependency_lib = ARGV.fetch(2)
117
+
118
+ require "torikago"
119
+
120
+ container = Torikago::EngineContainer.new(
121
+ name: :foo,
122
+ module_root: module_root,
123
+ gemfile: "Gemfile",
124
+ gemfile_dependency_loader: lambda do |path|
125
+ raise "unexpected Gemfile path: \#{path}" unless path.to_s == File.join(module_root, "Gemfile")
126
+
127
+ [{ name: "example-gem", requirement: "= 1.2.3", require_paths: [dependency_lib] }]
128
+ end,
129
+ gem_activator: lambda do |_dependency|
130
+ raise "gem activator should not be called when Ruby::Box is active"
131
+ end
132
+ )
133
+
134
+ raise "unexpected result" unless container.call("Foo::DependencyVersionQuery") == "module-local"
135
+
136
+ puts "ok"
137
+ RUBY
138
+ module_root,
139
+ dependency_lib
140
+ )
141
+ end
142
+ end
143
+
144
+ def test_call_resolves_path_gem_require_paths_inside_ruby_box
145
+ Dir.mktmpdir("torikago-engine-container") do |module_root|
146
+ dependency_lib = File.join(module_root, "vendor/example-gem-1.0.0/lib")
147
+ FileUtils.mkdir_p(dependency_lib)
148
+ File.write(
149
+ File.join(module_root, "Gemfile"),
150
+ <<~RUBY
151
+ source "https://rubygems.org"
152
+
153
+ gem "example-gem", path: "vendor/example-gem-1.0.0"
154
+ RUBY
155
+ )
156
+ File.write(
157
+ File.join(module_root, "vendor/example-gem-1.0.0/example-gem.gemspec"),
158
+ <<~RUBY
159
+ Gem::Specification.new do |spec|
160
+ spec.name = "example-gem"
161
+ spec.version = "1.0.0"
162
+ spec.summary = "test gem"
163
+ spec.authors = ["torikago"]
164
+ spec.files = ["lib/shared_dependency.rb"]
165
+ spec.require_paths = ["lib"]
166
+ end
167
+ RUBY
168
+ )
169
+ File.write(
170
+ File.join(dependency_lib, "shared_dependency.rb"),
171
+ <<~RUBY
172
+ module SharedDependency
173
+ VERSION = "module-local"
174
+ end
175
+ RUBY
176
+ )
177
+
178
+ package_api_dir = File.join(module_root, "app/package_api/foo")
179
+ FileUtils.mkdir_p(package_api_dir)
180
+ File.write(
181
+ File.join(package_api_dir, "dependency_version_query.rb"),
182
+ <<~RUBY
183
+ require "shared_dependency"
184
+
185
+ class Foo::DependencyVersionQuery
186
+ def call
187
+ SharedDependency::VERSION
188
+ end
189
+ end
190
+ RUBY
191
+ )
192
+
193
+ assert_ruby_box_child_process(
194
+ <<~RUBY,
195
+ $LOAD_PATH.unshift(ARGV.fetch(0))
196
+ module_root = ARGV.fetch(1)
197
+
198
+ require "torikago"
199
+
200
+ container = Torikago::EngineContainer.new(
201
+ name: :foo,
202
+ module_root: module_root,
203
+ gemfile: "Gemfile"
204
+ )
205
+
206
+ raise "unexpected result" unless container.call("Foo::DependencyVersionQuery") == "module-local"
207
+
208
+ puts "ok"
209
+ RUBY
210
+ module_root
211
+ )
212
+ end
213
+ end
214
+
215
+ def test_call_resolves_path_gem_require_paths_from_the_module_gemfile
216
+ Dir.mktmpdir("torikago-engine-container") do |module_root|
217
+ dependency_root = File.join(module_root, "vendor/versioned_formatter")
218
+ dependency_lib = File.join(dependency_root, "lib")
219
+ FileUtils.mkdir_p(dependency_lib)
220
+ File.write(
221
+ File.join(dependency_root, "versioned_formatter.gemspec"),
222
+ <<~RUBY
223
+ Gem::Specification.new do |spec|
224
+ spec.name = "versioned_formatter"
225
+ spec.version = "1.0.0"
226
+ spec.summary = "test gem"
227
+ spec.authors = ["torikago"]
228
+ spec.files = ["lib/versioned_formatter.rb"]
229
+ spec.require_paths = ["lib"]
230
+ end
231
+ RUBY
232
+ )
233
+ File.write(
234
+ File.join(dependency_lib, "versioned_formatter.rb"),
235
+ <<~RUBY
236
+ module VersionedFormatter
237
+ VERSION = "1.0.0"
238
+ end
239
+ RUBY
240
+ )
241
+ File.write(
242
+ File.join(module_root, "Gemfile"),
243
+ <<~RUBY
244
+ source "https://rubygems.org"
245
+
246
+ gem "versioned_formatter", path: "vendor/versioned_formatter"
247
+ RUBY
248
+ )
249
+
250
+ package_api_dir = File.join(module_root, "app/package_api/foo")
251
+ FileUtils.mkdir_p(package_api_dir)
252
+ File.write(
253
+ File.join(package_api_dir, "gemfile_dependency_query.rb"),
254
+ <<~RUBY
255
+ require "versioned_formatter"
256
+
257
+ class Foo::GemfileDependencyQuery
258
+ def call
259
+ VersionedFormatter::VERSION
260
+ end
261
+ end
262
+ RUBY
263
+ )
264
+
265
+ assert_ruby_box_child_process(
266
+ <<~RUBY,
267
+ $LOAD_PATH.unshift(ARGV.fetch(0))
268
+ module_root = ARGV.fetch(1)
269
+
270
+ require "torikago"
271
+
272
+ container = Torikago::EngineContainer.new(
273
+ name: :foo,
274
+ module_root: module_root,
275
+ gemfile: "Gemfile"
276
+ )
277
+
278
+ raise "unexpected result" unless container.call("Foo::GemfileDependencyQuery") == "1.0.0"
279
+
280
+ puts "ok"
281
+ RUBY
282
+ module_root
283
+ )
284
+ end
285
+ end
286
+
287
+ def test_call_resolves_exact_installed_gem_require_paths_after_a_different_version_is_active
288
+ skip("requires rake 13.3.1 and 13.4.2") unless installed_gem?("rake", "= 13.3.1") && installed_gem?("rake", "= 13.4.2")
289
+
290
+ Dir.mktmpdir("torikago-engine-container") do |module_root|
291
+ File.write(
292
+ File.join(module_root, "Gemfile"),
293
+ <<~RUBY
294
+ source "https://rubygems.org"
295
+
296
+ gem "rake", "= 13.3.1"
297
+ RUBY
298
+ )
299
+
300
+ Kernel.send(:gem, "rake", "= 13.4.2")
301
+ require "rake"
302
+
303
+ container = Torikago::EngineContainer.new(
304
+ name: :foo,
305
+ module_root: module_root,
306
+ gemfile: "Gemfile"
307
+ )
308
+
309
+ dependencies = container.send(:load_gemfile_dependencies, Pathname(File.join(module_root, "Gemfile")))
310
+
311
+ assert_equal "rake", dependencies.fetch(0).fetch(:name)
312
+ assert_equal "= 13.3.1", dependencies.fetch(0).fetch(:requirement)
313
+ assert_match(%r{/rake-13\.3\.1/lib\z}, dependencies.fetch(0).fetch(:require_paths).first)
314
+ end
315
+ end
316
+
317
+ def test_call_reports_missing_installed_gemfile_dependencies_clearly
318
+ with_module_root do |module_root|
319
+ File.write(
320
+ File.join(module_root, "Gemfile"),
321
+ <<~RUBY
322
+ source "https://rubygems.org"
323
+
324
+ gem "example-gem", "= 9.9.9"
325
+ RUBY
326
+ )
327
+
328
+ container = Torikago::EngineContainer.new(
329
+ name: :foo,
330
+ module_root: module_root,
331
+ gemfile: "Gemfile"
332
+ )
333
+
334
+ error = assert_raises(Torikago::GemfileOverrideError) do
335
+ container.call("Foo::ListProductsQuery")
336
+ end
337
+
338
+ assert_match(/example-gem/, error.message)
339
+ assert_match(/foo/, error.message)
340
+ end
341
+ end
342
+
343
+ def test_call_loads_configured_setup_before_public_api
344
+ with_module_root do |module_root|
345
+ setup_dir = File.join(module_root, "config")
346
+ FileUtils.mkdir_p(setup_dir)
347
+ File.write(
348
+ File.join(setup_dir, "box_setup.rb"),
349
+ <<~RUBY
350
+ module SetupProbe
351
+ VALUE = "patched"
352
+ end
353
+ RUBY
354
+ )
355
+
356
+ File.write(
357
+ File.join(module_root, "app/package_api/foo/setup_aware_query.rb"),
358
+ <<~RUBY
359
+ class Foo::SetupAwareQuery
360
+ def call
361
+ SetupProbe::VALUE
362
+ end
363
+ end
364
+ RUBY
365
+ )
366
+
367
+ container = Torikago::EngineContainer.new(
368
+ name: :foo,
369
+ module_root: module_root,
370
+ setup: "config/box_setup.rb"
371
+ )
372
+
373
+ assert_equal "patched", container.call("Foo::SetupAwareQuery")
374
+ end
375
+ end
376
+
377
+ def test_call_loads_setup_only_once
378
+ with_module_root do |module_root|
379
+ setup_dir = File.join(module_root, "config")
380
+ FileUtils.mkdir_p(setup_dir)
381
+ File.write(
382
+ File.join(setup_dir, "box_setup.rb"),
383
+ <<~RUBY
384
+ module SetupProbe
385
+ RUNS = (const_defined?(:RUNS) ? RUNS + 1 : 1)
386
+ end
387
+ RUBY
388
+ )
389
+
390
+ File.write(
391
+ File.join(module_root, "app/package_api/foo/setup_count_query.rb"),
392
+ <<~RUBY
393
+ class Foo::SetupCountQuery
394
+ def call
395
+ SetupProbe::RUNS
396
+ end
397
+ end
398
+ RUBY
399
+ )
400
+
401
+ container = Torikago::EngineContainer.new(
402
+ name: :foo,
403
+ module_root: module_root,
404
+ setup: "config/box_setup.rb"
405
+ )
406
+
407
+ assert_equal 1, container.call("Foo::SetupCountQuery")
408
+ assert_equal 1, container.call("Foo::SetupCountQuery")
409
+ end
410
+ end
411
+
412
+ def test_call_raises_load_error_when_setup_is_missing
413
+ with_module_root do |module_root|
414
+ container = Torikago::EngineContainer.new(
415
+ name: :foo,
416
+ module_root: module_root,
417
+ setup: "config/missing_setup.rb"
418
+ )
419
+
420
+ error = assert_raises(LoadError) do
421
+ container.call("Foo::ListProductsQuery")
422
+ end
423
+
424
+ assert_match(/setup not found/, error.message)
425
+ assert_match(/missing_setup\.rb/, error.message)
426
+ end
427
+ end
428
+
429
+ def test_call_loads_plain_gateway_models_without_eager_loading_rails_models
430
+ with_module_root do |module_root|
431
+ model_dir = File.join(module_root, "app/models/foo")
432
+ FileUtils.mkdir_p(model_dir)
433
+ File.write(
434
+ File.join(model_dir, "order_store.rb"),
435
+ <<~RUBY
436
+ class Foo::OrderStore
437
+ def self.all
438
+ ["order"]
439
+ end
440
+ end
441
+ RUBY
442
+ )
443
+ File.write(
444
+ File.join(model_dir, "foo_record.rb"),
445
+ <<~RUBY
446
+ raise "ActiveRecord models should not be eager-loaded by Gateway"
447
+
448
+ class Foo::FooRecord < ActiveRecord::Base
449
+ end
450
+ RUBY
451
+ )
452
+ File.write(
453
+ File.join(module_root, "app/package_api/foo/list_orders_query.rb"),
454
+ <<~RUBY
455
+ class Foo::ListOrdersQuery
456
+ def call
457
+ Foo::OrderStore.all
458
+ end
459
+ end
460
+ RUBY
461
+ )
462
+
463
+ container = Torikago::EngineContainer.new(name: :foo, module_root: module_root)
464
+
465
+ assert_equal ["order"], container.call("Foo::ListOrdersQuery")
466
+ end
467
+ end
468
+
469
+ private
470
+
471
+ def with_module_root
472
+ Dir.mktmpdir("torikago-engine-container") do |module_root|
473
+ package_api_dir = File.join(module_root, "app/package_api/foo")
474
+ FileUtils.mkdir_p(package_api_dir)
475
+
476
+ File.write(
477
+ File.join(package_api_dir, "list_products_query.rb"),
478
+ <<~RUBY
479
+ class Foo::ListProductsQuery
480
+ def call
481
+ ["coffee-beans", "drip-bag"]
482
+ end
483
+ end
484
+ RUBY
485
+ )
486
+
487
+ File.write(
488
+ File.join(package_api_dir, "current_box_query.rb"),
489
+ <<~RUBY
490
+ class Foo::CurrentBoxQuery
491
+ def call
492
+ Torikago::CurrentExecution.current_box
493
+ end
494
+ end
495
+ RUBY
496
+ )
497
+ yield module_root
498
+ end
499
+ end
500
+
501
+ def with_custom_entrypoint_module_root
502
+ Dir.mktmpdir("torikago-engine-container") do |module_root|
503
+ package_api_dir = File.join(module_root, "components/public_api/foo")
504
+ FileUtils.mkdir_p(package_api_dir)
505
+
506
+ File.write(
507
+ File.join(package_api_dir, "custom_entry_point_query.rb"),
508
+ <<~RUBY
509
+ class Foo::CustomEntryPointQuery
510
+ def call
511
+ "custom entrypoint"
512
+ end
513
+ end
514
+ RUBY
515
+ )
516
+ yield module_root
517
+ end
518
+ end
519
+
520
+ def assert_ruby_box_child_process(script, *args)
521
+ stdout, stderr, status = Open3.capture3(
522
+ { "RUBY_BOX" => "1" },
523
+ RbConfig.ruby,
524
+ "-e",
525
+ script,
526
+ File.expand_path("../../lib", __dir__),
527
+ *args
528
+ )
529
+
530
+ assert_predicate status, :success?, stderr
531
+ assert_equal "ok\n", stdout
532
+ end
533
+
534
+ def installed_gem?(name, requirement)
535
+ return true unless installed_specs_for(name, requirement).empty?
536
+
537
+ gem_requirement = Gem::Requirement.new(requirement)
538
+ Gem::Specification.dirs.any? do |specification_dir|
539
+ Dir[File.join(specification_dir, "#{name}-*.gemspec")].any? do |gemspec_path|
540
+ spec = Gem::Specification.load(gemspec_path)
541
+ spec && spec.name == name && gem_requirement.satisfied_by?(spec.version)
542
+ end
543
+ end
544
+ end
545
+
546
+ def installed_specs_for(name, requirement)
547
+ Gem::Specification.find_all_by_name(name, requirement)
548
+ end
549
+ end
@@ -0,0 +1,155 @@
1
+ require_relative "../test_helper"
2
+ require "fileutils"
3
+ require "tmpdir"
4
+
5
+ class TorikagoGatewayTest < Minitest::Test
6
+ FakeContainer = Struct.new(:calls) do
7
+ def call(public_api_class_name, *args, **kwargs)
8
+ calls << [public_api_class_name, args, kwargs]
9
+ "result for #{public_api_class_name}"
10
+ end
11
+ end
12
+
13
+ class FakeRegistry
14
+ def initialize(containers)
15
+ @containers = containers
16
+ @resolved = []
17
+ end
18
+
19
+ attr_reader :resolved
20
+
21
+ def resolve(name)
22
+ normalized_name = name.to_sym
23
+ resolved << normalized_name
24
+ @containers.fetch(normalized_name)
25
+ end
26
+ end
27
+
28
+ def test_class_level_call_delegates_to_the_shared_gateway
29
+ original_gateway = Torikago.instance_variable_get(:@gateway)
30
+ fake_gateway = Object.new
31
+ called_with = nil
32
+
33
+ fake_gateway.define_singleton_method(:call) do |*args, **kwargs|
34
+ called_with = [args, kwargs]
35
+ "ok"
36
+ end
37
+
38
+ Torikago.instance_variable_set(:@gateway, fake_gateway)
39
+
40
+ result = Torikago::Gateway.call("Foo::ListProductsQuery", page: 1)
41
+
42
+ assert_equal "ok", result
43
+ assert_equal [["Foo::ListProductsQuery"], { page: 1 }], called_with
44
+ ensure
45
+ Torikago.instance_variable_set(:@gateway, original_gateway)
46
+ end
47
+
48
+ def test_call_delegates_to_the_target_module_container
49
+ configuration = Torikago::Configuration.new
50
+ configuration.register(:foo, root: "/modules/foo")
51
+ write_package_api_manifest("/modules/foo", "Foo::ListProductsQuery" => { "allowed_callers" => [] })
52
+
53
+ container = FakeContainer.new([])
54
+ registry = FakeRegistry.new(foo: container)
55
+ gateway = Torikago::Gateway.new(
56
+ registry: registry,
57
+ configuration: configuration,
58
+ manifest_loader: ->(_definition) { { "exports" => { "Foo::ListProductsQuery" => { "allowed_callers" => [] } } } }
59
+ )
60
+
61
+ result = gateway.call("Foo::ListProductsQuery", page: 1)
62
+
63
+ assert_equal "result for Foo::ListProductsQuery", result
64
+ assert_equal [:foo], registry.resolved
65
+ assert_equal [["Foo::ListProductsQuery", [], { page: 1 }]], container.calls
66
+ end
67
+
68
+ def test_call_rejects_public_api_not_declared_in_package_api_manifest
69
+ configuration = Torikago::Configuration.new
70
+ configuration.register(:foo, root: "/modules/foo")
71
+ registry = FakeRegistry.new(foo: FakeContainer.new([]))
72
+ gateway = Torikago::Gateway.new(
73
+ registry: registry,
74
+ configuration: configuration,
75
+ manifest_loader: ->(_definition) { { "exports" => {} } }
76
+ )
77
+
78
+ error = assert_raises(Torikago::PublicApiError) do
79
+ gateway.call("Foo::MissingCommand")
80
+ end
81
+
82
+ assert_match(/Foo::MissingCommand/, error.message)
83
+ end
84
+
85
+ def test_call_allows_host_app_invocation_without_allowed_callers
86
+ configuration = Torikago::Configuration.new
87
+ configuration.register(:foo, root: "/modules/foo")
88
+ container = FakeContainer.new([])
89
+ registry = FakeRegistry.new(foo: container)
90
+ gateway = Torikago::Gateway.new(
91
+ registry: registry,
92
+ configuration: configuration,
93
+ manifest_loader: ->(_definition) { { "exports" => { "Foo::ListProductsQuery" => { "allowed_callers" => [] } } } }
94
+ )
95
+
96
+ gateway.call("Foo::ListProductsQuery")
97
+
98
+ assert_equal [["Foo::ListProductsQuery", [], {}]], container.calls
99
+ end
100
+
101
+ def test_call_allows_box_dependency_declared_in_package_api_manifest
102
+ configuration = Torikago::Configuration.new
103
+ configuration.register(:foo, root: "/modules/foo")
104
+ configuration.register(:bar, root: "/modules/bar")
105
+ bar_container = FakeContainer.new([])
106
+ registry = FakeRegistry.new(foo: FakeContainer.new([]), bar: bar_container)
107
+
108
+ gateway = Torikago::Gateway.new(
109
+ registry: registry,
110
+ configuration: configuration,
111
+ manifest_loader: lambda do |definition|
112
+ if definition.name == :bar
113
+ { "exports" => { "Bar::SubmitOrderCommand" => { "allowed_callers" => ["foo"] } } }
114
+ else
115
+ { "exports" => {} }
116
+ end
117
+ end
118
+ )
119
+
120
+ Torikago::CurrentExecution.with_box(:foo) do
121
+ result = gateway.call("Bar::SubmitOrderCommand", order_id: 1)
122
+
123
+ assert_equal "result for Bar::SubmitOrderCommand", result
124
+ end
125
+
126
+ assert_equal [["Bar::SubmitOrderCommand", [], { order_id: 1 }]], bar_container.calls
127
+ end
128
+
129
+ def test_call_rejects_box_dependency_not_declared_in_package_api_manifest
130
+ configuration = Torikago::Configuration.new
131
+ configuration.register(:foo, root: "/modules/foo")
132
+ configuration.register(:bar, root: "/modules/bar")
133
+ registry = FakeRegistry.new(foo: FakeContainer.new([]), bar: FakeContainer.new([]))
134
+
135
+ gateway = Torikago::Gateway.new(
136
+ registry: registry,
137
+ configuration: configuration,
138
+ manifest_loader: ->(_definition) { { "exports" => { "Bar::SubmitOrderCommand" => { "allowed_callers" => ["admin"] } } } }
139
+ )
140
+
141
+ error = assert_raises(Torikago::DependencyError) do
142
+ Torikago::CurrentExecution.with_box(:foo) do
143
+ gateway.call("Bar::SubmitOrderCommand")
144
+ end
145
+ end
146
+
147
+ assert_match(/foo/, error.message)
148
+ assert_match(/bar/i, error.message)
149
+ end
150
+
151
+ private
152
+
153
+ def write_package_api_manifest(_root, _entries)
154
+ end
155
+ end