@quenty/binder 14.40.0 → 14.41.0

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.
@@ -1,155 +1,25 @@
1
1
  --!strict
2
2
  --[[
3
- Comprehensive coverage for Binder.
4
-
5
- Runtime binders are booted the way production code boots them: registered on a BinderProvider
6
- that is initialized and started through a ServiceBag, and torn down through serviceBag:Destroy().
7
- Adornees are parented into a workspace container because CollectionService.GetInstanceAddedSignal
8
- only fires for instances that live in the DataModel. A bind that happens after :Start() is awaited
9
- event-driven through `binder:Promise(inst):Yield()`, never a fixed sleep. Tags are global and the
10
- test place is shared across a batch run, so every test uses a distinct tag and cleans up after
11
- itself.
12
-
13
- A handful of tests exercise Binder's standalone lifecycle contract (:new/:Init/:Start guards,
14
- :Create) and construct the binder directly -- there is no other way to assert, for example, that
15
- :Start() is idempotent when called twice by hand.
16
-
17
3
  @class Binder.spec.lua
18
4
  ]]
19
5
 
20
6
  local require = require(script.Parent.loader).load(script)
21
7
 
22
8
  local Binder = require("Binder")
23
- local BinderProvider = require("BinderProvider")
9
+ local BinderTestUtils = require("BinderTestUtils")
24
10
  local Jest = require("Jest")
25
- local ServiceBag = require("ServiceBag")
26
11
 
27
12
  local describe = Jest.Globals.describe
28
13
  local expect = Jest.Globals.expect
29
14
  local it = Jest.Globals.it
30
15
 
31
- local specCounter = 0
32
-
33
- -- A minimal bound class that records its instance and whether it was destroyed. It deliberately
34
- -- does NOT retain its constructor varargs: the ServiceBag is injected as a constructor arg, and its
35
- -- object graph contains Quenty Signals whose strict __index makes jest's deep-equality traversal
36
- -- throw. Keeping the class free of them lets toEqual compare instances safely.
37
- local function makeTrackingClass()
38
- local Class = {}
39
- Class.__index = Class
40
- Class.ClassName = "TrackingClass"
41
-
42
- function Class.new(inst)
43
- local self = setmetatable({}, Class)
44
- self.instance = inst
45
- self.destroyed = false
46
- return self
47
- end
48
-
49
- function Class:Destroy()
50
- self.destroyed = true
51
- end
52
-
53
- return Class
54
- end
55
-
56
- -- Returns once `inst` is no longer bound. CollectionService tag removal is synchronous here, so the
57
- -- class is usually already gone by the time we check; the guarded wait also covers a deferred case.
58
- local function awaitUnbound(binder, inst)
59
- if binder:Get(inst) ~= nil then
60
- binder:GetClassRemovedSignal():Wait()
61
- end
62
- end
63
-
64
- -- A no-op constructor that still returns a value, so Binder's generic bound type stays inhabited.
65
- local function noopConstructor()
66
- return {}
67
- end
68
-
69
- local function setup()
70
- specCounter += 1
71
- local suffix = specCounter
72
-
73
- local serviceBag = ServiceBag.new()
74
- local serviceBagDestroyed = false
75
-
76
- local container = Instance.new("Folder")
77
- container.Name = "BinderSpecContainer"
78
- container.Parent = workspace
79
-
80
- local instances = {}
81
- local pendingBinders: { any } = {}
82
- local extraTagCounter = 0
83
- local booted = false
84
-
85
- local function uniqueTag(): string
86
- extraTagCounter += 1
87
- return string.format("BinderSpecTag_%d_%d", suffix, extraTagCounter)
88
- end
89
-
90
- -- Registers a binder to be booted by boot(); returns the binder so the test can tag/query it.
91
- -- The constructor is intentionally untyped (any) so per-test generic inference does not leak
92
- -- into this shared helper.
93
- local function addBinder(constructor: any, ...): Binder.Binder<any>
94
- assert(not booted, "Cannot add a binder after boot()")
95
- local binder = Binder.new(uniqueTag(), constructor, ...)
96
- table.insert(pendingBinders, binder)
97
- return binder
98
- end
99
-
100
- -- Boots the registered binders through a ServiceBag, exactly as production code does.
101
- local function boot()
102
- assert(not booted, "Already booted")
103
- booted = true
104
-
105
- local binders = pendingBinders
106
- local provider = BinderProvider.new(string.format("BinderSpecProvider_%d", suffix), function(self)
107
- for _, binder in binders do
108
- self:Add(binder)
109
- end
110
- end)
111
-
112
- serviceBag:GetService(provider)
113
- serviceBag:Init()
114
- serviceBag:Start()
115
- end
116
-
117
- local function newInstance(parent: Instance?, className: string?): Instance
118
- local inst = Instance.new(className or "Folder")
119
- inst.Parent = parent or container
120
- table.insert(instances, inst)
121
- return inst
122
- end
123
-
124
- local function destroyServiceBag()
125
- if not serviceBagDestroyed then
126
- serviceBagDestroyed = true
127
- serviceBag:Destroy()
128
- end
129
- end
130
-
131
- return {
132
- container = container,
133
- uniqueTag = uniqueTag,
134
- addBinder = addBinder,
135
- boot = boot,
136
- newInstance = newInstance,
137
- destroyServiceBag = destroyServiceBag,
138
- destroy = function()
139
- destroyServiceBag()
140
- for _, inst in instances do
141
- pcall(function()
142
- inst:Destroy()
143
- end)
144
- end
145
- container:Destroy()
146
- end,
147
- }
148
- end
16
+ local setup = BinderTestUtils.setup
17
+ local makeTrackingClass = BinderTestUtils.makeTrackingClass
18
+ local awaitUnbound = BinderTestUtils.awaitUnbound
19
+ local noopConstructor = BinderTestUtils.noopConstructor
149
20
 
150
21
  describe("Binder.new()", function()
151
22
  it("constructs a binder", function()
152
- -- Never Init'd/Started, so it holds no resources and needs no teardown.
153
23
  local binder = Binder.new("BinderNewSpecTag", noopConstructor)
154
24
  expect(Binder.isBinder(binder)).toEqual(true)
155
25
  end)
@@ -173,16 +43,14 @@ describe("Binder.new()", function()
173
43
  end)
174
44
 
175
45
  it("captures variadic constructor args", function()
176
- local env = setup()
46
+ local controller = setup()
177
47
 
178
- -- Explicit .new()-time args take precedence over the ServiceBag that Init would otherwise
179
- -- inject, so this class only ever captures the "a"/"b" passed here.
180
- local binder = env.addBinder(function(_inst, a, b)
48
+ local binder = controller.addBinder(function(_inst, a, b)
181
49
  return { a = a, b = b }
182
50
  end, "a", "b")
183
- env.boot()
51
+ controller.boot()
184
52
 
185
- local inst = env.newInstance()
53
+ local inst = controller.newInstance()
186
54
  binder:Tag(inst)
187
55
 
188
56
  local ok, class = binder:Promise(inst):Yield()
@@ -190,7 +58,7 @@ describe("Binder.new()", function()
190
58
  expect(class.a).toEqual("a")
191
59
  expect(class.b).toEqual("b")
192
60
 
193
- env.destroy()
61
+ controller.destroy()
194
62
  end)
195
63
  end)
196
64
 
@@ -226,14 +94,14 @@ end)
226
94
 
227
95
  describe("Binder constructor variants", function()
228
96
  it("supports a plain function constructor", function()
229
- local env = setup()
97
+ local controller = setup()
230
98
 
231
- local binder = env.addBinder(function(inst)
99
+ local binder = controller.addBinder(function(inst)
232
100
  return { instance = inst, kind = "function" }
233
101
  end)
234
- env.boot()
102
+ controller.boot()
235
103
 
236
- local inst = env.newInstance()
104
+ local inst = controller.newInstance()
237
105
  binder:Tag(inst)
238
106
 
239
107
  local ok, class = binder:Promise(inst):Yield()
@@ -241,45 +109,45 @@ describe("Binder constructor variants", function()
241
109
  expect(class.kind).toEqual("function")
242
110
  expect(class.instance).toEqual(inst)
243
111
 
244
- env.destroy()
112
+ controller.destroy()
245
113
  end)
246
114
 
247
115
  it("supports a class table with .new", function()
248
- local env = setup()
116
+ local controller = setup()
249
117
 
250
118
  local Class = makeTrackingClass()
251
- local binder = env.addBinder(Class)
252
- env.boot()
119
+ local binder = controller.addBinder(Class)
120
+ controller.boot()
253
121
 
254
- local inst = env.newInstance()
122
+ local inst = controller.newInstance()
255
123
  binder:Tag(inst)
256
124
 
257
125
  local ok, class = binder:Promise(inst):Yield()
258
126
  assert(ok, "Never bound")
259
127
  expect(class.instance).toEqual(inst)
260
128
 
261
- env.destroy()
129
+ controller.destroy()
262
130
  end)
263
131
 
264
132
  it("supports a provider table with :Create", function()
265
- local env = setup()
133
+ local controller = setup()
266
134
 
267
135
  local provider = {}
268
136
  function provider.Create(_self, inst)
269
137
  return { instance = inst, kind = "provider" }
270
138
  end
271
139
 
272
- local binder = env.addBinder(provider :: any)
273
- env.boot()
140
+ local binder = controller.addBinder(provider :: any)
141
+ controller.boot()
274
142
 
275
- local inst = env.newInstance()
143
+ local inst = controller.newInstance()
276
144
  binder:Tag(inst)
277
145
 
278
146
  local ok, class = binder:Promise(inst):Yield()
279
147
  assert(ok, "Never bound")
280
148
  expect(class.kind).toEqual("provider")
281
149
 
282
- env.destroy()
150
+ controller.destroy()
283
151
  end)
284
152
  end)
285
153
 
@@ -312,88 +180,87 @@ end)
312
180
 
313
181
  describe("Binder binding via ServiceBag", function()
314
182
  it("binds instances tagged before start", function()
315
- local env = setup()
183
+ local controller = setup()
316
184
 
317
185
  local Class = makeTrackingClass()
318
- local binder = env.addBinder(Class)
186
+ local binder = controller.addBinder(Class)
319
187
 
320
- local inst = env.newInstance()
321
- binder:Tag(inst) -- tag before the service bag starts the binder
188
+ local inst = controller.newInstance()
189
+ binder:Tag(inst)
322
190
 
323
- env.boot()
191
+ controller.boot()
324
192
 
325
- -- Pre-tagged instances bind synchronously as the binder starts.
326
193
  expect(binder:Get(inst)).never.toBeNil()
327
194
 
328
- env.destroy()
195
+ controller.destroy()
329
196
  end)
330
197
 
331
198
  it("binds instances tagged after start", function()
332
- local env = setup()
199
+ local controller = setup()
333
200
 
334
- local binder = env.addBinder(makeTrackingClass())
335
- env.boot()
201
+ local binder = controller.addBinder(makeTrackingClass())
202
+ controller.boot()
336
203
 
337
- local inst = env.newInstance()
204
+ local inst = controller.newInstance()
338
205
  binder:Tag(inst)
339
206
 
340
207
  local ok = binder:Promise(inst):Yield()
341
208
  expect(ok).toEqual(true)
342
209
 
343
- env.destroy()
210
+ controller.destroy()
344
211
  end)
345
212
  end)
346
213
 
347
214
  describe("Binder:Get()", function()
348
215
  it("returns nil for an unbound instance", function()
349
- local env = setup()
216
+ local controller = setup()
350
217
 
351
- local binder = env.addBinder(function() end)
352
- env.boot()
218
+ local binder = controller.addBinder(function() end)
219
+ controller.boot()
353
220
 
354
- expect(binder:Get(env.newInstance())).toBeNil()
221
+ expect(binder:Get(controller.newInstance())).toBeNil()
355
222
 
356
- env.destroy()
223
+ controller.destroy()
357
224
  end)
358
225
 
359
226
  it("throws when passed a non-instance", function()
360
- local env = setup()
227
+ local controller = setup()
361
228
 
362
- local binder = env.addBinder(function() end)
363
- env.boot()
229
+ local binder = controller.addBinder(function() end)
230
+ controller.boot()
364
231
 
365
232
  expect(function()
366
233
  binder:Get(5 :: any)
367
234
  end).toThrow()
368
235
 
369
- env.destroy()
236
+ controller.destroy()
370
237
  end)
371
238
  end)
372
239
 
373
240
  describe("Binder tagging", function()
374
241
  it("Tag/HasTag/Untag manage the collection service tag", function()
375
- local env = setup()
242
+ local controller = setup()
376
243
 
377
- local binder = env.addBinder(function() end)
378
- env.boot()
244
+ local binder = controller.addBinder(function() end)
245
+ controller.boot()
379
246
 
380
- local inst = env.newInstance()
247
+ local inst = controller.newInstance()
381
248
  expect(binder:HasTag(inst)).toEqual(false)
382
249
  binder:Tag(inst)
383
250
  expect(binder:HasTag(inst)).toEqual(true)
384
251
  binder:Untag(inst)
385
252
  expect(binder:HasTag(inst)).toEqual(false)
386
253
 
387
- env.destroy()
254
+ controller.destroy()
388
255
  end)
389
256
 
390
257
  it("Bind tags and Unbind untags on the server", function()
391
- local env = setup()
258
+ local controller = setup()
392
259
 
393
- local binder = env.addBinder(makeTrackingClass())
394
- env.boot()
260
+ local binder = controller.addBinder(makeTrackingClass())
261
+ controller.boot()
395
262
 
396
- local inst = env.newInstance()
263
+ local inst = controller.newInstance()
397
264
  binder:Bind(inst)
398
265
  expect(binder:HasTag(inst)).toEqual(true)
399
266
 
@@ -403,7 +270,7 @@ describe("Binder tagging", function()
403
270
  binder:Unbind(inst)
404
271
  expect(binder:HasTag(inst)).toEqual(false)
405
272
 
406
- env.destroy()
273
+ controller.destroy()
407
274
  end)
408
275
  end)
409
276
 
@@ -439,13 +306,13 @@ end)
439
306
 
440
307
  describe("Binder:GetAll() / GetAllSet()", function()
441
308
  it("tracks every bound class", function()
442
- local env = setup()
309
+ local controller = setup()
443
310
 
444
- local binder = env.addBinder(makeTrackingClass())
445
- env.boot()
311
+ local binder = controller.addBinder(makeTrackingClass())
312
+ controller.boot()
446
313
 
447
- local instA = env.newInstance()
448
- local instB = env.newInstance()
314
+ local instA = controller.newInstance()
315
+ local instB = controller.newInstance()
449
316
  binder:Tag(instA)
450
317
  binder:Tag(instB)
451
318
 
@@ -458,29 +325,29 @@ describe("Binder:GetAll() / GetAllSet()", function()
458
325
  expect(set[binder:Get(instA)]).toEqual(true)
459
326
  expect(set[binder:Get(instB)]).toEqual(true)
460
327
 
461
- env.destroy()
328
+ controller.destroy()
462
329
  end)
463
330
  end)
464
331
 
465
332
  describe("Binder signals", function()
466
333
  it("memoizes the added/removing/removed signals", function()
467
- local env = setup()
334
+ local controller = setup()
468
335
 
469
- local binder = env.addBinder(function() end)
470
- env.boot()
336
+ local binder = controller.addBinder(function() end)
337
+ controller.boot()
471
338
 
472
339
  expect(binder:GetClassAddedSignal()).toEqual(binder:GetClassAddedSignal())
473
340
  expect(binder:GetClassRemovingSignal()).toEqual(binder:GetClassRemovingSignal())
474
341
  expect(binder:GetClassRemovedSignal()).toEqual(binder:GetClassRemovedSignal())
475
342
 
476
- env.destroy()
343
+ controller.destroy()
477
344
  end)
478
345
 
479
346
  it("fires the added signal with the class and instance", function()
480
- local env = setup()
347
+ local controller = setup()
481
348
 
482
- local binder = env.addBinder(makeTrackingClass())
483
- env.boot()
349
+ local binder = controller.addBinder(makeTrackingClass())
350
+ controller.boot()
484
351
 
485
352
  local firedClass, firedInst
486
353
  binder:GetClassAddedSignal():Connect(function(class, inst)
@@ -488,21 +355,21 @@ describe("Binder signals", function()
488
355
  firedInst = inst
489
356
  end)
490
357
 
491
- local inst = env.newInstance()
358
+ local inst = controller.newInstance()
492
359
  binder:Tag(inst)
493
360
  assert((binder:Promise(inst):Yield()), "Never bound")
494
361
 
495
362
  expect(firedInst).toEqual(inst)
496
363
  expect(firedClass).toEqual(binder:Get(inst))
497
364
 
498
- env.destroy()
365
+ controller.destroy()
499
366
  end)
500
367
 
501
368
  it("fires removing then removed on unbind", function()
502
- local env = setup()
369
+ local controller = setup()
503
370
 
504
- local binder = env.addBinder(makeTrackingClass())
505
- env.boot()
371
+ local binder = controller.addBinder(makeTrackingClass())
372
+ controller.boot()
506
373
 
507
374
  local order = {}
508
375
  binder:GetClassRemovingSignal():Connect(function()
@@ -512,7 +379,7 @@ describe("Binder signals", function()
512
379
  table.insert(order, "removed")
513
380
  end)
514
381
 
515
- local inst = env.newInstance()
382
+ local inst = controller.newInstance()
516
383
  binder:Tag(inst)
517
384
  assert((binder:Promise(inst):Yield()), "Never bound")
518
385
 
@@ -522,16 +389,16 @@ describe("Binder signals", function()
522
389
  expect(order[1]).toEqual("removing")
523
390
  expect(order[2]).toEqual("removed")
524
391
 
525
- env.destroy()
392
+ controller.destroy()
526
393
  end)
527
394
 
528
395
  it("destroys the bound class when it is removed", function()
529
- local env = setup()
396
+ local controller = setup()
530
397
 
531
- local binder = env.addBinder(makeTrackingClass())
532
- env.boot()
398
+ local binder = controller.addBinder(makeTrackingClass())
399
+ controller.boot()
533
400
 
534
- local inst = env.newInstance()
401
+ local inst = controller.newInstance()
535
402
  binder:Tag(inst)
536
403
  local ok, class = binder:Promise(inst):Yield()
537
404
  assert(ok, "Never bound")
@@ -541,18 +408,18 @@ describe("Binder signals", function()
541
408
 
542
409
  expect(class.destroyed).toEqual(true)
543
410
 
544
- env.destroy()
411
+ controller.destroy()
545
412
  end)
546
413
  end)
547
414
 
548
415
  describe("Binder:ObserveInstance()", function()
549
416
  it("fires with the class on bind and nil on unbind", function()
550
- local env = setup()
417
+ local controller = setup()
551
418
 
552
- local binder = env.addBinder(makeTrackingClass())
553
- env.boot()
419
+ local binder = controller.addBinder(makeTrackingClass())
420
+ controller.boot()
554
421
 
555
- local inst = env.newInstance()
422
+ local inst = controller.newInstance()
556
423
 
557
424
  -- Wrap each emission so a nil value is still recorded (table.insert(t, nil) is a no-op).
558
425
  local emissions = {}
@@ -573,16 +440,16 @@ describe("Binder:ObserveInstance()", function()
573
440
 
574
441
  cleanup()
575
442
 
576
- env.destroy()
443
+ controller.destroy()
577
444
  end)
578
445
 
579
446
  it("returns a cleanup that stops future callbacks", function()
580
- local env = setup()
447
+ local controller = setup()
581
448
 
582
- local binder = env.addBinder(makeTrackingClass())
583
- env.boot()
449
+ local binder = controller.addBinder(makeTrackingClass())
450
+ controller.boot()
584
451
 
585
- local inst = env.newInstance()
452
+ local inst = controller.newInstance()
586
453
 
587
454
  local count = 0
588
455
  local cleanup = binder:ObserveInstance(inst, function()
@@ -595,34 +462,34 @@ describe("Binder:ObserveInstance()", function()
595
462
 
596
463
  expect(count).toEqual(0)
597
464
 
598
- env.destroy()
465
+ controller.destroy()
599
466
  end)
600
467
 
601
468
  it("throws for a non-instance or non-function", function()
602
- local env = setup()
469
+ local controller = setup()
603
470
 
604
- local binder = env.addBinder(function() end)
605
- env.boot()
471
+ local binder = controller.addBinder(function() end)
472
+ controller.boot()
606
473
 
607
474
  expect(function()
608
475
  binder:ObserveInstance(5 :: any, function() end)
609
476
  end).toThrow()
610
477
  expect(function()
611
- binder:ObserveInstance(env.newInstance(), 5 :: any)
478
+ binder:ObserveInstance(controller.newInstance(), 5 :: any)
612
479
  end).toThrow()
613
480
 
614
- env.destroy()
481
+ controller.destroy()
615
482
  end)
616
483
  end)
617
484
 
618
485
  describe("Binder:Observe()", function()
619
486
  it("emits the current value on subscribe and updates on bind", function()
620
- local env = setup()
487
+ local controller = setup()
621
488
 
622
- local binder = env.addBinder(makeTrackingClass())
623
- env.boot()
489
+ local binder = controller.addBinder(makeTrackingClass())
490
+ controller.boot()
624
491
 
625
- local inst = env.newInstance()
492
+ local inst = controller.newInstance()
626
493
 
627
494
  -- Wrap each emission so the initial nil value is still recorded.
628
495
  local emissions = {}
@@ -630,7 +497,6 @@ describe("Binder:Observe()", function()
630
497
  table.insert(emissions, { value = class })
631
498
  end)
632
499
 
633
- -- First emission is the (nil) current value.
634
500
  expect(#emissions).toEqual(1)
635
501
  expect(emissions[1].value).toBeNil()
636
502
 
@@ -641,81 +507,80 @@ describe("Binder:Observe()", function()
641
507
  expect(emissions[2].value).toEqual(binder:Get(inst))
642
508
 
643
509
  sub:Destroy()
644
- env.destroy()
510
+ controller.destroy()
645
511
  end)
646
512
  end)
647
513
 
648
514
  describe("Binder:Promise()", function()
649
515
  it("resolves immediately when already bound", function()
650
- local env = setup()
516
+ local controller = setup()
651
517
 
652
- local binder = env.addBinder(makeTrackingClass())
518
+ local binder = controller.addBinder(makeTrackingClass())
653
519
 
654
- local inst = env.newInstance()
520
+ local inst = controller.newInstance()
655
521
  binder:Tag(inst)
656
- env.boot()
522
+ controller.boot()
657
523
 
658
524
  local promise = binder:Promise(inst)
659
525
  expect(promise:IsFulfilled()).toEqual(true)
660
526
 
661
- env.destroy()
527
+ controller.destroy()
662
528
  end)
663
529
 
664
530
  it("throws when passed a non-instance", function()
665
- local env = setup()
531
+ local controller = setup()
666
532
 
667
- local binder = env.addBinder(function() end)
668
- env.boot()
533
+ local binder = controller.addBinder(function() end)
534
+ controller.boot()
669
535
 
670
536
  expect(function()
671
537
  binder:Promise(5 :: any)
672
538
  end).toThrow()
673
539
 
674
- env.destroy()
540
+ controller.destroy()
675
541
  end)
676
542
  end)
677
543
 
678
544
  describe("Binder:_add() dedupe", function()
679
545
  it("does not rebind an already-bound instance", function()
680
- local env = setup()
546
+ local controller = setup()
681
547
 
682
548
  local constructed = 0
683
- local binder = env.addBinder(function(inst)
549
+ local binder = controller.addBinder(function(inst)
684
550
  constructed += 1
685
551
  return { instance = inst }
686
552
  end)
687
- env.boot()
553
+ controller.boot()
688
554
 
689
- local inst = env.newInstance()
555
+ local inst = controller.newInstance()
690
556
  binder:Tag(inst)
691
557
  assert((binder:Promise(inst):Yield()), "Never bound")
692
558
 
693
- -- Re-tagging an already-tagged instance must not reconstruct.
694
559
  binder:Tag(inst)
695
560
  task.wait()
696
561
 
697
562
  expect(constructed).toEqual(1)
698
563
 
699
- env.destroy()
564
+ controller.destroy()
700
565
  end)
701
566
  end)
702
567
 
703
568
  describe("Binder teardown", function()
704
569
  it("removes and destroys all bound classes when the service bag is destroyed", function()
705
- local env = setup()
570
+ local controller = setup()
706
571
 
707
- local binder = env.addBinder(makeTrackingClass())
708
- env.boot()
572
+ local binder = controller.addBinder(makeTrackingClass())
573
+ controller.boot()
709
574
 
710
- local inst = env.newInstance()
575
+ local inst = controller.newInstance()
711
576
  binder:Tag(inst)
712
577
  local ok, class = binder:Promise(inst):Yield()
713
578
  assert(ok, "Never bound")
714
579
 
715
- env.destroyServiceBag()
580
+ controller.destroyServiceBag()
716
581
 
717
582
  expect(class.destroyed).toEqual(true)
718
583
 
719
- env.destroy()
584
+ controller.destroy()
720
585
  end)
721
586
  end)