@quenty/steputils 3.7.2 → 3.9.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [3.9.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/steputils@3.8.0...@quenty/steputils@3.9.0) (2026-08-28)
7
+
8
+ **Note:** Version bump only for package @quenty/steputils
9
+
10
+ # [3.8.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/steputils@3.7.2...@quenty/steputils@3.8.0) (2026-08-28)
11
+
12
+ **Note:** Version bump only for package @quenty/steputils
13
+
6
14
  ## [3.7.2](https://github.com/Quenty/NevermoreEngine/compare/@quenty/steputils@3.7.1...@quenty/steputils@3.7.2) (2026-08-14)
7
15
 
8
16
  **Note:** Version bump only for package @quenty/steputils
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/steputils",
3
- "version": "3.7.2",
3
+ "version": "3.9.0",
4
4
  "description": "Binds animations into step, where the animation only runs as needed",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -28,12 +28,14 @@
28
28
  "Quenty"
29
29
  ],
30
30
  "dependencies": {
31
+ "@quenty/jestutils": "1.1.0",
31
32
  "@quenty/loader": "10.11.1",
32
- "@quenty/nevermore-test-runner": "1.5.1",
33
+ "@quenty/maid": "3.12.0",
34
+ "@quenty/nevermore-test-runner": "1.6.0",
33
35
  "@quentystudios/jest-lua": "3.10.0-quenty.2"
34
36
  },
35
37
  "publishConfig": {
36
38
  "access": "public"
37
39
  },
38
- "gitHead": "f084360c3729ea424d49d9bc42f8f0d1c128fa82"
40
+ "gitHead": "346201e192e467cb71160f43029863853be855b5"
39
41
  }
@@ -8,6 +8,8 @@ local require = require(script.Parent.loader).load(script)
8
8
  local RunService = game:GetService("RunService")
9
9
 
10
10
  local Jest = require("Jest")
11
+ local JestUtils = require("JestUtils")
12
+ local Maid = require("Maid")
11
13
  local StepUtils = require("StepUtils")
12
14
 
13
15
  local describe = Jest.Globals.describe
@@ -21,13 +23,23 @@ type Controller = {
21
23
  bindStepped: ((...any) -> boolean) -> ((...any) -> (), () -> ()),
22
24
  track: (() -> ()) -> () -> (),
23
25
  stepFrames: (number) -> (),
24
- destroy: () -> (),
26
+ Destroy: (self: Controller) -> (),
25
27
  }
26
28
 
27
29
  local function setup(): Controller
30
+ local maid = Maid.new()
28
31
  local instances: { Instance } = {}
29
32
  local cleanups: { () -> () } = {}
30
33
 
34
+ maid:GiveTask(function()
35
+ for _, cleanup in cleanups do
36
+ cleanup()
37
+ end
38
+ for _, inst in instances do
39
+ inst:Destroy()
40
+ end
41
+ end)
42
+
31
43
  local function track(cleanup: () -> ()): () -> ()
32
44
  table.insert(cleanups, cleanup)
33
45
  return cleanup
@@ -66,16 +78,13 @@ local function setup(): Controller
66
78
  end
67
79
  end,
68
80
 
69
- destroy = function()
70
- for _, cleanup in cleanups do
71
- cleanup()
72
- end
73
- for _, inst in instances do
74
- inst:Destroy()
75
- end
81
+ Destroy = function(_self)
82
+ maid:DoCleaning()
76
83
  end,
77
84
  }
78
85
 
86
+ maid:GiveTask(JestUtils.afterThis(controller))
87
+
79
88
  return controller
80
89
  end
81
90
 
@@ -85,7 +94,7 @@ describe("StepUtils.getAnimationStepSignal", function()
85
94
 
86
95
  expect(typeof(StepUtils.getAnimationStepSignal())).toBe("RBXScriptSignal")
87
96
 
88
- controller.destroy()
97
+ controller:Destroy()
89
98
  end)
90
99
 
91
100
  it("falls back to Heartbeat off a running client", function()
@@ -93,7 +102,7 @@ describe("StepUtils.getAnimationStepSignal", function()
93
102
 
94
103
  expect(StepUtils.getAnimationStepSignal()).toBe(RunService.Heartbeat)
95
104
 
96
- controller.destroy()
105
+ controller:Destroy()
97
106
  end)
98
107
 
99
108
  it("returns a signal that actually fires here", function()
@@ -111,7 +120,7 @@ describe("StepUtils.getAnimationStepSignal", function()
111
120
 
112
121
  expect(fired).toBe(true)
113
122
 
114
- controller.destroy()
123
+ controller:Destroy()
115
124
  end)
116
125
  end)
117
126
 
@@ -121,7 +130,7 @@ describe("StepUtils.getSteppedSignal", function()
121
130
 
122
131
  expect(typeof(StepUtils.getSteppedSignal())).toBe("RBXScriptSignal")
123
132
 
124
- controller.destroy()
133
+ controller:Destroy()
125
134
  end)
126
135
 
127
136
  it("falls back to Heartbeat on a non-running DataModel", function()
@@ -130,7 +139,7 @@ describe("StepUtils.getSteppedSignal", function()
130
139
  expect(StepUtils.getSteppedSignal()).toBe(RunService.Heartbeat)
131
140
  expect(StepUtils.getSteppedSignal()).never.toBe(RunService.Stepped)
132
141
 
133
- controller.destroy()
142
+ controller:Destroy()
134
143
  end)
135
144
 
136
145
  it("returns a signal that actually fires here", function()
@@ -148,7 +157,7 @@ describe("StepUtils.getSteppedSignal", function()
148
157
 
149
158
  expect(fired).toBe(true)
150
159
 
151
- controller.destroy()
160
+ controller:Destroy()
152
161
  end)
153
162
  end)
154
163
 
@@ -167,7 +176,7 @@ describe("StepUtils.bindToSignal", function()
167
176
 
168
177
  expect(calls).toBe(1)
169
178
 
170
- controller.destroy()
179
+ controller:Destroy()
171
180
  end)
172
181
 
173
182
  it("does not connect when the first update returns false", function()
@@ -186,7 +195,7 @@ describe("StepUtils.bindToSignal", function()
186
195
 
187
196
  expect(calls).toBe(1)
188
197
 
189
- controller.destroy()
198
+ controller:Destroy()
190
199
  end)
191
200
 
192
201
  it("keeps invoking the update while it returns true", function()
@@ -205,7 +214,7 @@ describe("StepUtils.bindToSignal", function()
205
214
 
206
215
  expect(calls).toBe(3)
207
216
 
208
- controller.destroy()
217
+ controller:Destroy()
209
218
  end)
210
219
 
211
220
  it("stops invoking the update once it returns false", function()
@@ -225,7 +234,7 @@ describe("StepUtils.bindToSignal", function()
225
234
 
226
235
  expect(calls).toBe(2)
227
236
 
228
- controller.destroy()
237
+ controller:Destroy()
229
238
  end)
230
239
 
231
240
  it("forwards the connect arguments to every later update", function()
@@ -244,7 +253,7 @@ describe("StepUtils.bindToSignal", function()
244
253
 
245
254
  expect(seen).toEqual({ "self", "self", "self" })
246
255
 
247
- controller.destroy()
256
+ controller:Destroy()
248
257
  end)
249
258
 
250
259
  it("ignores the signal's own arguments", function()
@@ -262,7 +271,7 @@ describe("StepUtils.bindToSignal", function()
262
271
 
263
272
  expect(seen).toEqual({ { value = nil }, { value = nil } })
264
273
 
265
- controller.destroy()
274
+ controller:Destroy()
266
275
  end)
267
276
 
268
277
  it("ignores a repeated connect while already connected", function()
@@ -280,7 +289,7 @@ describe("StepUtils.bindToSignal", function()
280
289
 
281
290
  expect(calls).toBe(1)
282
291
 
283
- controller.destroy()
292
+ controller:Destroy()
284
293
  end)
285
294
 
286
295
  it("reconnects after an explicit disconnect", function()
@@ -303,7 +312,7 @@ describe("StepUtils.bindToSignal", function()
303
312
 
304
313
  expect(calls).toBe(3)
305
314
 
306
- controller.destroy()
315
+ controller:Destroy()
307
316
  end)
308
317
 
309
318
  it("tolerates disconnect before connect and repeated disconnects", function()
@@ -319,7 +328,7 @@ describe("StepUtils.bindToSignal", function()
319
328
  disconnect()
320
329
  end).never.toThrow()
321
330
 
322
- controller.destroy()
331
+ controller:Destroy()
323
332
  end)
324
333
 
325
334
  it("throws on something that is not a signal", function()
@@ -331,7 +340,7 @@ describe("StepUtils.bindToSignal", function()
331
340
  end)
332
341
  end).toThrow()
333
342
 
334
- controller.destroy()
343
+ controller:Destroy()
335
344
  end)
336
345
 
337
346
  it("throws on a non-function update", function()
@@ -342,7 +351,7 @@ describe("StepUtils.bindToSignal", function()
342
351
  (StepUtils :: any).bindToSignal(bindable.Event, "update")
343
352
  end).toThrow()
344
353
 
345
- controller.destroy()
354
+ controller:Destroy()
346
355
  end)
347
356
  end)
348
357
 
@@ -361,7 +370,7 @@ describe("StepUtils.bindToRenderStep", function()
361
370
 
362
371
  expect(calls).toBe(3)
363
372
 
364
- controller.destroy()
373
+ controller:Destroy()
365
374
  end)
366
375
 
367
376
  it("does not bind when the first update returns false", function()
@@ -378,7 +387,7 @@ describe("StepUtils.bindToRenderStep", function()
378
387
 
379
388
  expect(calls).toBe(1)
380
389
 
381
- controller.destroy()
390
+ controller:Destroy()
382
391
  end)
383
392
 
384
393
  it("stops driving the update after disconnect", function()
@@ -399,7 +408,7 @@ describe("StepUtils.bindToRenderStep", function()
399
408
 
400
409
  expect(calls).toBe(afterDisconnect)
401
410
 
402
- controller.destroy()
411
+ controller:Destroy()
403
412
  end)
404
413
  end)
405
414
 
@@ -417,7 +426,7 @@ describe("StepUtils.bindToStepped", function()
417
426
 
418
427
  expect(calls).toBe(1)
419
428
 
420
- controller.destroy()
429
+ controller:Destroy()
421
430
  end)
422
431
 
423
432
  it("tolerates disconnect before connect", function()
@@ -431,7 +440,7 @@ describe("StepUtils.bindToStepped", function()
431
440
  disconnect()
432
441
  end).never.toThrow()
433
442
 
434
- controller.destroy()
443
+ controller:Destroy()
435
444
  end)
436
445
  end)
437
446
 
@@ -449,7 +458,7 @@ describe("StepUtils.deferWait", function()
449
458
 
450
459
  expect(order).toEqual({ "deferred", "resumed" })
451
460
 
452
- controller.destroy()
461
+ controller:Destroy()
453
462
  end)
454
463
  end)
455
464
 
@@ -467,7 +476,7 @@ describe("StepUtils.onceAtEvent", function()
467
476
 
468
477
  expect(calls).toBe(1)
469
478
 
470
- controller.destroy()
479
+ controller:Destroy()
471
480
  end)
472
481
 
473
482
  it("passes the event arguments through", function()
@@ -483,7 +492,7 @@ describe("StepUtils.onceAtEvent", function()
483
492
 
484
493
  expect(seen).toBe("payload")
485
494
 
486
- controller.destroy()
495
+ controller:Destroy()
487
496
  end)
488
497
 
489
498
  it("only invokes the function once", function()
@@ -500,7 +509,7 @@ describe("StepUtils.onceAtEvent", function()
500
509
 
501
510
  expect(calls).toBe(1)
502
511
 
503
- controller.destroy()
512
+ controller:Destroy()
504
513
  end)
505
514
 
506
515
  it("does not invoke the function once cancelled", function()
@@ -517,7 +526,7 @@ describe("StepUtils.onceAtEvent", function()
517
526
 
518
527
  expect(calls).toBe(0)
519
528
 
520
- controller.destroy()
529
+ controller:Destroy()
521
530
  end)
522
531
 
523
532
  it("tolerates cancelling after the function ran", function()
@@ -532,7 +541,7 @@ describe("StepUtils.onceAtEvent", function()
532
541
  cancel()
533
542
  end).never.toThrow()
534
543
 
535
- controller.destroy()
544
+ controller:Destroy()
536
545
  end)
537
546
 
538
547
  it("throws on a non-function", function()
@@ -543,7 +552,7 @@ describe("StepUtils.onceAtEvent", function()
543
552
  (StepUtils :: any).onceAtEvent(bindable.Event, "func")
544
553
  end).toThrow()
545
554
 
546
- controller.destroy()
555
+ controller:Destroy()
547
556
  end)
548
557
  end)
549
558
 
@@ -560,7 +569,7 @@ describe("StepUtils.onceAtRenderStepped", function()
560
569
 
561
570
  expect(calls).toBe(1)
562
571
 
563
- controller.destroy()
572
+ controller:Destroy()
564
573
  end)
565
574
 
566
575
  it("does not invoke the function once cancelled", function()
@@ -576,7 +585,7 @@ describe("StepUtils.onceAtRenderStepped", function()
576
585
 
577
586
  expect(calls).toBe(0)
578
587
 
579
- controller.destroy()
588
+ controller:Destroy()
580
589
  end)
581
590
  end)
582
591
 
@@ -595,7 +604,7 @@ describe("StepUtils.onceAtStepped", function()
595
604
  end).never.toThrow()
596
605
  expect(calls).toBe(0)
597
606
 
598
- controller.destroy()
607
+ controller:Destroy()
599
608
  end)
600
609
  end)
601
610
 
@@ -610,7 +619,7 @@ describe("StepUtils.onceAtRenderPriority", function()
610
619
  cancel()
611
620
  end).never.toThrow()
612
621
 
613
- controller.destroy()
622
+ controller:Destroy()
614
623
  end)
615
624
 
616
625
  it("throws on a non-number priority", function()
@@ -620,7 +629,7 @@ describe("StepUtils.onceAtRenderPriority", function()
620
629
  (StepUtils :: any).onceAtRenderPriority("high", function() end)
621
630
  end).toThrow()
622
631
 
623
- controller.destroy()
632
+ controller:Destroy()
624
633
  end)
625
634
 
626
635
  it("throws on a non-function", function()
@@ -630,6 +639,6 @@ describe("StepUtils.onceAtRenderPriority", function()
630
639
  (StepUtils :: any).onceAtRenderPriority(100, "func")
631
640
  end).toThrow()
632
641
 
633
- controller.destroy()
642
+ controller:Destroy()
634
643
  end)
635
644
  end)
@@ -6,6 +6,8 @@
6
6
  local require = require(script.Parent.loader).load(script)
7
7
 
8
8
  local Jest = require("Jest")
9
+ local JestUtils = require("JestUtils")
10
+ local Maid = require("Maid")
9
11
  local onRenderStepFrame = require("onRenderStepFrame")
10
12
 
11
13
  local describe = Jest.Globals.describe
@@ -14,12 +16,19 @@ local it = Jest.Globals.it
14
16
 
15
17
  type Controller = {
16
18
  bind: (number, () -> ()) -> () -> (),
17
- destroy: () -> (),
19
+ Destroy: (self: Controller) -> (),
18
20
  }
19
21
 
20
22
  local function setup(): Controller
23
+ local maid = Maid.new()
21
24
  local unbinds: { () -> () } = {}
22
25
 
26
+ maid:GiveTask(function()
27
+ for _, unbind in unbinds do
28
+ unbind()
29
+ end
30
+ end)
31
+
23
32
  local controller: Controller = {
24
33
  bind = function(priority: number, callback: () -> ())
25
34
  local unbind = onRenderStepFrame(priority, callback)
@@ -27,13 +36,13 @@ local function setup(): Controller
27
36
  return unbind
28
37
  end,
29
38
 
30
- destroy = function()
31
- for _, unbind in unbinds do
32
- unbind()
33
- end
39
+ Destroy = function(_self)
40
+ maid:DoCleaning()
34
41
  end,
35
42
  }
36
43
 
44
+ maid:GiveTask(JestUtils.afterThis(controller))
45
+
37
46
  return controller
38
47
  end
39
48
 
@@ -45,7 +54,7 @@ describe("onRenderStepFrame", function()
45
54
 
46
55
  expect(type(unbind)).toBe("function")
47
56
 
48
- controller.destroy()
57
+ controller:Destroy()
49
58
  end)
50
59
 
51
60
  it("tolerates a repeated unbind", function()
@@ -58,7 +67,7 @@ describe("onRenderStepFrame", function()
58
67
  unbind()
59
68
  end).never.toThrow()
60
69
 
61
- controller.destroy()
70
+ controller:Destroy()
62
71
  end)
63
72
 
64
73
  it("binds each call under its own key", function()
@@ -73,7 +82,7 @@ describe("onRenderStepFrame", function()
73
82
  second()
74
83
  end).never.toThrow()
75
84
 
76
- controller.destroy()
85
+ controller:Destroy()
77
86
  end)
78
87
 
79
88
  it("throws on a non-number priority", function()
@@ -83,7 +92,7 @@ describe("onRenderStepFrame", function()
83
92
  (onRenderStepFrame :: any)("high", function() end)
84
93
  end).toThrow()
85
94
 
86
- controller.destroy()
95
+ controller:Destroy()
87
96
  end)
88
97
 
89
98
  it("throws on a non-function callback", function()
@@ -93,6 +102,6 @@ describe("onRenderStepFrame", function()
93
102
  (onRenderStepFrame :: any)(100, "callback")
94
103
  end).toThrow()
95
104
 
96
- controller.destroy()
105
+ controller:Destroy()
97
106
  end)
98
107
  end)
@@ -6,6 +6,8 @@
6
6
  local require = require(script.Parent.loader).load(script)
7
7
 
8
8
  local Jest = require("Jest")
9
+ local JestUtils = require("JestUtils")
10
+ local Maid = require("Maid")
9
11
  local onSteppedFrame = require("onSteppedFrame")
10
12
 
11
13
  local describe = Jest.Globals.describe
@@ -14,12 +16,19 @@ local it = Jest.Globals.it
14
16
 
15
17
  type Controller = {
16
18
  bind: (() -> ()) -> RBXScriptConnection,
17
- destroy: () -> (),
19
+ Destroy: (self: Controller) -> (),
18
20
  }
19
21
 
20
22
  local function setup(): Controller
23
+ local maid = Maid.new()
21
24
  local connections: { RBXScriptConnection } = {}
22
25
 
26
+ maid:GiveTask(function()
27
+ for _, conn in connections do
28
+ conn:Disconnect()
29
+ end
30
+ end)
31
+
23
32
  local controller: Controller = {
24
33
  bind = function(callback)
25
34
  local conn = onSteppedFrame(callback)
@@ -27,13 +36,13 @@ local function setup(): Controller
27
36
  return conn
28
37
  end,
29
38
 
30
- destroy = function()
31
- for _, conn in connections do
32
- conn:Disconnect()
33
- end
39
+ Destroy = function(_self)
40
+ maid:DoCleaning()
34
41
  end,
35
42
  }
36
43
 
44
+ maid:GiveTask(JestUtils.afterThis(controller))
45
+
37
46
  return controller
38
47
  end
39
48
 
@@ -46,7 +55,7 @@ describe("onSteppedFrame", function()
46
55
  expect(typeof(conn)).toBe("RBXScriptConnection")
47
56
  expect(conn.Connected).toBe(true)
48
57
 
49
- controller.destroy()
58
+ controller:Destroy()
50
59
  end)
51
60
 
52
61
  it("goes dead once disconnected", function()
@@ -57,7 +66,7 @@ describe("onSteppedFrame", function()
57
66
 
58
67
  expect(conn.Connected).toBe(false)
59
68
 
60
- controller.destroy()
69
+ controller:Destroy()
61
70
  end)
62
71
 
63
72
  it("tolerates a repeated disconnect", function()
@@ -70,7 +79,7 @@ describe("onSteppedFrame", function()
70
79
  conn:Disconnect()
71
80
  end).never.toThrow()
72
81
 
73
- controller.destroy()
82
+ controller:Destroy()
74
83
  end)
75
84
 
76
85
  it("throws on a non-function", function()
@@ -80,6 +89,6 @@ describe("onSteppedFrame", function()
80
89
  (onSteppedFrame :: any)("func")
81
90
  end).toThrow()
82
91
 
83
- controller.destroy()
92
+ controller:Destroy()
84
93
  end)
85
94
  end)