@rbxts/planck 0.2.5 → 0.3.0-alpha.2

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,313 @@
1
+ --!nonstrict
2
+ local RunService = game:GetService("RunService")
3
+ local ReplicatedStorage = game:GetService("ReplicatedStorage")
4
+
5
+ local root = script.Parent.Parent
6
+
7
+ local Phase = require(root.Phase)
8
+ local Scheduler = require(root.Scheduler)
9
+ local Pipeline = require(root.Pipeline)
10
+
11
+ local JestGlobals = require(ReplicatedStorage.DevPackages.JestGlobals)
12
+
13
+ local describe = JestGlobals.describe
14
+ local expect = JestGlobals.expect
15
+ local test = JestGlobals.test
16
+
17
+ describe("scheduler", function()
18
+ describe("insert", function()
19
+ test("phase", function()
20
+ local myPhase = Phase.new("myPhase")
21
+ local myScheduler = Scheduler.new():insert(myPhase)
22
+
23
+ local orderedPhases =
24
+ myScheduler._defaultDependencyGraph:getOrderedList()
25
+ local mainIndex =
26
+ table.find(orderedPhases, myScheduler._defaultPhase)
27
+
28
+ expect(orderedPhases[mainIndex - 1]).toBe(myPhase)
29
+ end)
30
+
31
+ test("phase with event", function()
32
+ local myPhase = Phase.new("myPhase")
33
+
34
+ local myScheduler = Scheduler.new()
35
+ :insert(myPhase, RunService, "Heartbeat")
36
+
37
+ local identifier = `{RunService}@Heartbeat`
38
+ local dependencyGraph =
39
+ myScheduler._eventDependencyGraphs[identifier]
40
+
41
+ expect(dependencyGraph).toBeTruthy()
42
+ expect(myScheduler._connectedEvents[identifier]).toBeTruthy()
43
+
44
+ local orderedList = dependencyGraph:getOrderedList()
45
+ expect(orderedList[#orderedList]).toBe(myPhase)
46
+ end)
47
+
48
+ test("pipeline", function()
49
+ local myPhase = Phase.new()
50
+ local otherPhase = Phase.new()
51
+
52
+ local myPipeline =
53
+ Pipeline.new("myPipeline"):insert(myPhase):insert(otherPhase)
54
+
55
+ local myScheduler = Scheduler.new():insert(myPipeline)
56
+
57
+ local orderedDependencies =
58
+ myScheduler._defaultDependencyGraph:getOrderedList()
59
+ local mainIndex =
60
+ table.find(orderedDependencies, myScheduler._defaultPhase)
61
+
62
+ expect(orderedDependencies[mainIndex - 1]).toBe(myPipeline)
63
+
64
+ local orderedPhases = myPipeline.dependencyGraph:getOrderedList()
65
+ expect(orderedPhases[1]).toBe(myPhase)
66
+ expect(orderedPhases[2]).toBe(otherPhase)
67
+ end)
68
+
69
+ test("pipeline with event", function()
70
+ local myPhase = Phase.new()
71
+ local otherPhase = Phase.new()
72
+
73
+ local myPipeline =
74
+ Pipeline.new("myPipeline"):insert(myPhase):insert(otherPhase)
75
+
76
+ local myScheduler = Scheduler.new()
77
+ :insert(myPipeline, RunService, "Heartbeat")
78
+
79
+ local identifier = `{RunService}@Heartbeat`
80
+ local dependencyGraph =
81
+ myScheduler._eventDependencyGraphs[identifier]
82
+
83
+ expect(dependencyGraph).toBeTruthy()
84
+ expect(myScheduler._connectedEvents[identifier]).toBeTruthy()
85
+
86
+ local orderedList = dependencyGraph:getOrderedList()
87
+ expect(orderedList[1]).toBe(myPipeline)
88
+
89
+ local orderedPhases = myPipeline.dependencyGraph:getOrderedList()
90
+ expect(orderedPhases[1]).toBe(myPhase)
91
+ expect(orderedPhases[2]).toBe(otherPhase)
92
+ end)
93
+ end)
94
+
95
+ describe("insertAfter", function()
96
+ test("phase", function()
97
+ local phaseOne = Phase.new("phaseOne")
98
+ local phaseTwo = Phase.new("phaseTwo")
99
+ local phaseThree = Phase.new("phaseThree")
100
+
101
+ local myScheduler = Scheduler.new()
102
+ :insert(phaseOne)
103
+ :insert(phaseTwo)
104
+ :insertAfter(phaseThree, phaseOne)
105
+
106
+ local orderedPhases =
107
+ myScheduler._defaultDependencyGraph:getOrderedList()
108
+ local mainIndex =
109
+ table.find(orderedPhases, myScheduler._defaultPhase)
110
+
111
+ expect(orderedPhases[mainIndex - 3]).toBe(phaseOne)
112
+ expect(orderedPhases[mainIndex - 2]).toBe(phaseTwo)
113
+ expect(orderedPhases[mainIndex - 1]).toBe(phaseThree)
114
+ end)
115
+
116
+ test("pipeline", function()
117
+ local phaseOne = Phase.new("phaseOne")
118
+ local phaseTwo = Phase.new("phaseTwo")
119
+ local phaseThree = Phase.new("phaseThree")
120
+ local phaseFour = Phase.new("phaseFour")
121
+
122
+ local pipelineOne = Pipeline.new():insert(phaseOne):insert(phaseTwo)
123
+ local pipelineTwo = Pipeline.new():insert(phaseFour)
124
+ local pipelineThree = Pipeline.new():insert(phaseThree)
125
+
126
+ local myScheduler = Scheduler.new()
127
+ :insert(pipelineOne)
128
+ :insert(pipelineTwo)
129
+ :insertAfter(pipelineThree, pipelineOne)
130
+
131
+ local orderedDependencies =
132
+ myScheduler._defaultDependencyGraph:getOrderedList()
133
+ local mainIndex =
134
+ table.find(orderedDependencies, myScheduler._defaultPhase)
135
+
136
+ expect(orderedDependencies[mainIndex - 3]).toBe(pipelineOne)
137
+ expect(orderedDependencies[mainIndex - 2]).toBe(pipelineTwo)
138
+ expect(orderedDependencies[mainIndex - 1]).toBe(pipelineThree)
139
+ end)
140
+ end)
141
+
142
+ test("phase run condition", function()
143
+ expect.assertions(1)
144
+
145
+ local bool = true
146
+
147
+ local system = function(...)
148
+ expect({ ... }).toEqual({ 1, 2, 3 })
149
+ end
150
+
151
+ local myPhase = Phase.new("myPhase")
152
+ local myScheduler = Scheduler.new(1, 2, 3)
153
+ :insert(myPhase)
154
+ :addSystem(system, myPhase)
155
+ :addRunCondition(myPhase, function()
156
+ return bool
157
+ end)
158
+
159
+ myScheduler:runAll()
160
+
161
+ bool = false
162
+ myScheduler:runAll() -- Expect system to not run
163
+ end)
164
+
165
+ test("pipeline run condition", function()
166
+ expect.assertions(1)
167
+
168
+ local bool = true
169
+
170
+ local system = function(...)
171
+ expect({ ... }).toEqual({ 1, 2, 3 })
172
+ end
173
+
174
+ local myPhase = Phase.new("myPhase")
175
+
176
+ local myPipeline = Pipeline.new():insert(myPhase)
177
+
178
+ local myScheduler = Scheduler.new(1, 2, 3)
179
+ :insert(myPipeline)
180
+ :addSystem(system, myPhase)
181
+ :addRunCondition(myPipeline, function()
182
+ return bool
183
+ end)
184
+
185
+ myScheduler:run(myPipeline)
186
+
187
+ bool = false
188
+ myScheduler:run(myPipeline) -- Expect system to not run
189
+ end)
190
+
191
+ test("getDeltaTime", function()
192
+ local deltaTime
193
+
194
+ local myScheduler = Scheduler.new()
195
+
196
+ local system = function()
197
+ deltaTime = myScheduler:getDeltaTime()
198
+ end
199
+
200
+ myScheduler:addSystem(system)
201
+ myScheduler:run(system)
202
+ expect(deltaTime).toEqual(0)
203
+ myScheduler:run(system)
204
+ expect(deltaTime).never.toEqual(0)
205
+ end)
206
+
207
+ test("custom system name", function()
208
+ expect.assertions(5)
209
+
210
+ local myScheduler = Scheduler.new()
211
+
212
+ local function mySystem() end
213
+
214
+ myScheduler:addSystem({
215
+ name = "CustomSystemName",
216
+ system = mySystem,
217
+ })
218
+
219
+ expect(myScheduler._systemInfo[mySystem].name).toBe("CustomSystemName")
220
+
221
+ local function anotherSystem() end
222
+ myScheduler:addSystem(anotherSystem)
223
+
224
+ expect(myScheduler._systemInfo[anotherSystem].name).toBe(
225
+ "anotherSystem"
226
+ )
227
+
228
+ local function replacementSystem() end
229
+ myScheduler:replaceSystem(mySystem, {
230
+ name = "ReplacedSystemName",
231
+ system = replacementSystem,
232
+ })
233
+
234
+ expect(myScheduler._systemInfo[replacementSystem].name).toBe(
235
+ "ReplacedSystemName"
236
+ )
237
+
238
+ local function finalSystem() end
239
+ myScheduler:replaceSystem(replacementSystem, finalSystem)
240
+
241
+ expect(myScheduler._systemInfo[finalSystem].name).toBe("finalSystem")
242
+
243
+ expect(myScheduler._systemInfo[replacementSystem]).toBeNil()
244
+ end)
245
+
246
+ describe("startup systems", function()
247
+ test("should run once", function()
248
+ expect.assertions(1)
249
+
250
+ local myScheduler = Scheduler.new(1, 2, 3):addSystem(function(...)
251
+ expect({ ... }).toEqual({ 1, 2, 3 })
252
+ end, Phase.Startup)
253
+
254
+ myScheduler:runAll()
255
+ myScheduler:runAll()
256
+ end)
257
+
258
+ test("run before events once", function()
259
+ expect.assertions(1)
260
+
261
+ local myPhase = Phase.new("myPhase")
262
+ local bindableEvent = Instance.new("BindableEvent")
263
+
264
+ Scheduler.new(1, 2, 3)
265
+ :addSystem(function(...)
266
+ expect({ ... }).toEqual({ 1, 2, 3 })
267
+ end, Phase.Startup)
268
+ :insert(myPhase, bindableEvent, bindableEvent.Event)
269
+
270
+ bindableEvent:Fire()
271
+ task.wait()
272
+ bindableEvent:Fire()
273
+ task.wait()
274
+ end)
275
+
276
+ test("each run exactly once", function(_, done)
277
+ expect.assertions(3)
278
+
279
+ local myPhase = Phase.new("myPhase")
280
+ local bindableEvent = Instance.new("BindableEvent")
281
+
282
+ local n = 0
283
+ local ranOnce = false
284
+
285
+ Scheduler.new()
286
+ :addSystem(function()
287
+ n += 1
288
+ expect(n).toEqual(1)
289
+ end, Phase.PreStartup)
290
+ :addSystem(function()
291
+ n += 1
292
+ expect(n).toEqual(2)
293
+ end, Phase.Startup)
294
+ :addSystem(function()
295
+ n += 1
296
+ expect(n).toEqual(3)
297
+ end, Phase.PostStartup)
298
+ :insert(myPhase, bindableEvent, bindableEvent.Event)
299
+ :addSystem(function()
300
+ if ranOnce then
301
+ done()
302
+ end
303
+
304
+ ranOnce = true
305
+ end, myPhase)
306
+
307
+ bindableEvent:Fire()
308
+ task.wait()
309
+ bindableEvent:Fire()
310
+ task.wait()
311
+ end)
312
+ end)
313
+ end)
@@ -0,0 +1,147 @@
1
+ local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
+
3
+ local root = script.Parent.Parent
4
+
5
+ local Scheduler = require(root.Scheduler)
6
+ local conditions = require(root.conditions)
7
+
8
+ local isNot = conditions.isNot
9
+ local runOnce = conditions.runOnce
10
+ local timePassed = conditions.timePassed
11
+ local onEvent = conditions.onEvent
12
+
13
+ local JestGlobals = require(ReplicatedStorage.DevPackages.JestGlobals)
14
+
15
+ local describe = JestGlobals.describe
16
+ local expect = JestGlobals.expect
17
+ local test = JestGlobals.test
18
+
19
+ describe("conditions", function()
20
+ test("isNot", function()
21
+ expect.assertions(1)
22
+ local function system()
23
+ expect("Planckton!!!").toEqual(expect.anything())
24
+ end
25
+
26
+ local bool = false
27
+
28
+ local function condition()
29
+ return bool
30
+ end
31
+
32
+ local myScheduler = Scheduler.new()
33
+ :addSystem(system)
34
+ :addRunCondition(system, isNot(condition))
35
+
36
+ myScheduler:runAll() -- Expect to run
37
+
38
+ bool = true
39
+ myScheduler:runAll() -- Expect to not run
40
+ end)
41
+
42
+ test("runOnce", function()
43
+ expect.assertions(1)
44
+ local function system()
45
+ expect(true).toBe(true)
46
+ end
47
+
48
+ local myScheduler =
49
+ Scheduler.new():addSystem(system):addRunCondition(system, runOnce())
50
+
51
+ myScheduler:runAll() -- Expect to run
52
+ myScheduler:runAll() -- Expect to not run
53
+ end)
54
+
55
+ test("timePassed", function()
56
+ expect.assertions(3)
57
+ local didRun = false
58
+ local firstRun = false
59
+
60
+ local function system()
61
+ if firstRun then
62
+ didRun = true
63
+ end
64
+
65
+ firstRun = true
66
+ end
67
+
68
+ local myScheduler = Scheduler.new()
69
+ :addSystem(system)
70
+ :addRunCondition(system, timePassed(1))
71
+
72
+ myScheduler:runAll()
73
+ expect(didRun).toBe(false)
74
+ task.wait(0.5)
75
+
76
+ myScheduler:runAll()
77
+ expect(didRun).toBe(false)
78
+ task.wait(0.5)
79
+
80
+ myScheduler:runAll()
81
+ expect(didRun).toBe(true)
82
+ end)
83
+
84
+ test("onEvent", function()
85
+ expect.assertions(4)
86
+ local didRun = false
87
+ local bindableEvent = Instance.new("BindableEvent")
88
+
89
+ local function system()
90
+ didRun = true
91
+ end
92
+
93
+ local myScheduler = Scheduler.new():addSystem(system):addRunCondition(
94
+ system,
95
+ onEvent(bindableEvent, bindableEvent.Event)
96
+ )
97
+
98
+ myScheduler:runAll()
99
+ expect(didRun).toBe(false)
100
+ bindableEvent:Fire()
101
+ task.wait()
102
+
103
+ myScheduler:runAll()
104
+ expect(didRun).toBe(true)
105
+ didRun = false
106
+
107
+ myScheduler:runAll()
108
+ expect(didRun).toBe(false)
109
+ bindableEvent:Fire()
110
+ task.wait()
111
+
112
+ myScheduler:runAll()
113
+ expect(didRun).toBe(true)
114
+ end)
115
+
116
+ test("onEvent in SystemTable", function()
117
+ expect.assertions(4)
118
+ local didRun = false
119
+ local bindableEvent = Instance.new("BindableEvent")
120
+
121
+ local function system()
122
+ didRun = true
123
+ end
124
+
125
+ local myScheduler = Scheduler.new():addSystem({
126
+ system = system,
127
+ runConditions = { onEvent(bindableEvent, bindableEvent.Event) },
128
+ })
129
+
130
+ myScheduler:runAll()
131
+ expect(didRun).toBe(false)
132
+ bindableEvent:Fire()
133
+ task.wait()
134
+
135
+ myScheduler:runAll()
136
+ expect(didRun).toBe(true)
137
+ didRun = false
138
+
139
+ myScheduler:runAll()
140
+ expect(didRun).toBe(false)
141
+ bindableEvent:Fire()
142
+ task.wait()
143
+
144
+ myScheduler:runAll()
145
+ expect(didRun).toBe(true)
146
+ end)
147
+ end)
@@ -0,0 +1,54 @@
1
+ local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
+
3
+ local root = script.Parent.Parent
4
+
5
+ local Phase = require(root.Phase)
6
+ local Scheduler = require(root.Scheduler)
7
+
8
+ local JestGlobals = require(ReplicatedStorage.DevPackages.JestGlobals)
9
+
10
+ local describe = JestGlobals.describe
11
+ local expect = JestGlobals.expect
12
+ local test = JestGlobals.test
13
+
14
+ describe("topoRuntime", function()
15
+ test("useDeltaTime", function()
16
+ local matterHooks =
17
+ require(ReplicatedStorage.Packages.PlanckMatterHooks)
18
+ local useDeltaTime = matterHooks.useDeltaTime
19
+ expect.assertions(1)
20
+
21
+ local plugin = matterHooks.Plugin.new()
22
+
23
+ local myPhase = Phase.new("myPhase")
24
+ local myScheduler = Scheduler.new(1, 2, 3)
25
+ :addPlugin(plugin)
26
+ :insert(myPhase)
27
+ :addSystem(function()
28
+ expect(useDeltaTime()).toBeTruthy()
29
+ end, myPhase)
30
+
31
+ myScheduler:runAll()
32
+ end)
33
+
34
+ test("useThrottle", function()
35
+ local matterHooks =
36
+ require(ReplicatedStorage.Packages.PlanckMatterHooks)
37
+ local useThrottle = matterHooks.useThrottle
38
+ expect.assertions(1)
39
+
40
+ local plugin = matterHooks.Plugin.new()
41
+
42
+ local myPhase = Phase.new("myPhase")
43
+ local myScheduler = Scheduler.new(1, 2, 3)
44
+ :addPlugin(plugin)
45
+ :insert(myPhase)
46
+ :addSystem(function()
47
+ if useThrottle(1) then
48
+ expect(true).toBe(true)
49
+ end
50
+ end, myPhase)
51
+
52
+ myScheduler:runAll()
53
+ end)
54
+ end)
@@ -0,0 +1,192 @@
1
+ local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
+
3
+ local root = script.Parent.Parent
4
+
5
+ local Phase = require(root.Phase)
6
+ local Scheduler = require(root.Scheduler)
7
+
8
+ local JestGlobals = require(ReplicatedStorage.DevPackages.JestGlobals)
9
+
10
+ local describe = JestGlobals.describe
11
+ local expect = JestGlobals.expect
12
+ local test = JestGlobals.test
13
+
14
+ describe("systems", function()
15
+ test("add", function()
16
+ expect.assertions(1)
17
+
18
+ local myPhase = Phase.new("myPhase")
19
+ local myScheduler = Scheduler.new(1, 2, 3)
20
+ :insert(myPhase)
21
+ :addSystem(function(...)
22
+ expect({ ... }).toEqual({ 1, 2, 3 })
23
+ end, myPhase)
24
+
25
+ myScheduler:runAll()
26
+ end)
27
+
28
+ test("edit", function()
29
+ expect.assertions(2)
30
+
31
+ local function systemA(...)
32
+ expect({ ... }).toEqual({ 1, 2, 3 })
33
+ end
34
+
35
+ local myPhase = Phase.new("myPhase")
36
+ local myScheduler =
37
+ Scheduler.new(1, 2, 3):insert(myPhase):addSystem(systemA, myPhase)
38
+
39
+ myScheduler:runAll()
40
+
41
+ local otherPhase = Phase.new()
42
+ myScheduler:insert(otherPhase)
43
+
44
+ myScheduler:editSystem(systemA, otherPhase)
45
+ myScheduler:run(otherPhase)
46
+
47
+ -- Expect nothing to run here
48
+ myScheduler:run(myPhase)
49
+ end)
50
+
51
+ test("remove", function()
52
+ expect.assertions(1)
53
+
54
+ local function systemA(...)
55
+ expect({ ... }).toEqual({ 1, 2, 3 })
56
+ end
57
+
58
+ local myPhase = Phase.new("myPhase")
59
+ local myScheduler =
60
+ Scheduler.new(1, 2, 3):insert(myPhase):addSystem(systemA, myPhase)
61
+
62
+ myScheduler:runAll()
63
+
64
+ myScheduler:removeSystem(systemA)
65
+ myScheduler:runAll() -- Expect nothing here
66
+ end)
67
+
68
+ test("replace", function()
69
+ expect.assertions(3)
70
+
71
+ local function systemA(...)
72
+ expect({ ... }).toEqual({ 1, 2, 3 })
73
+ end
74
+
75
+ local function systemB(...)
76
+ -- FUTURE: Use Jest.spyOn
77
+ expect(true).toBe(true)
78
+ expect({ ... }).toEqual({ 1, 2, 3 })
79
+ end
80
+
81
+ local myPhase = Phase.new("myPhase")
82
+ local myScheduler =
83
+ Scheduler.new(1, 2, 3):insert(myPhase):addSystem(systemA, myPhase)
84
+
85
+ myScheduler:runAll()
86
+
87
+ myScheduler:replaceSystem(systemA, systemB)
88
+ myScheduler:runAll()
89
+ end)
90
+
91
+ test("system table", function()
92
+ expect.assertions(1)
93
+
94
+ local myPhase = Phase.new("myPhase")
95
+
96
+ local system = {
97
+ system = function(...)
98
+ expect({ ... }).toEqual({ 1, 2, 3 })
99
+ end,
100
+ phase = myPhase,
101
+ }
102
+
103
+ local myScheduler =
104
+ Scheduler.new(1, 2, 3):insert(myPhase):addSystem(system)
105
+
106
+ myScheduler:run(myPhase)
107
+ end)
108
+
109
+ test("run condition", function()
110
+ expect.assertions(1)
111
+
112
+ local bool = true
113
+
114
+ local system = function(...)
115
+ expect({ ... }).toEqual({ 1, 2, 3 })
116
+ end
117
+
118
+ local myPhase = Phase.new("myPhase")
119
+ local myScheduler = Scheduler.new(1, 2, 3)
120
+ :insert(myPhase)
121
+ :addSystem(system, myPhase)
122
+ :addRunCondition(system, function()
123
+ return bool
124
+ end)
125
+
126
+ myScheduler:runAll()
127
+
128
+ bool = false
129
+ myScheduler:runAll() -- Expect system to not run
130
+ end)
131
+
132
+ test("multiple run conditions", function()
133
+ expect.assertions(1)
134
+
135
+ local firstCondition = true
136
+ local secondCondition = true
137
+
138
+ local system = function(...)
139
+ expect({ ... }).toEqual({ 1, 2, 3 })
140
+ end
141
+
142
+ local myPhase = Phase.new("myPhase")
143
+ local myScheduler = Scheduler.new(1, 2, 3)
144
+ :insert(myPhase)
145
+ :addSystem(system, myPhase)
146
+ :addRunCondition(system, function()
147
+ return firstCondition
148
+ end)
149
+ :addRunCondition(system, function()
150
+ return secondCondition
151
+ end)
152
+
153
+ firstCondition = false
154
+ myScheduler:runAll()
155
+
156
+ firstCondition = true
157
+ secondCondition = false
158
+ myScheduler:runAll()
159
+
160
+ firstCondition = false
161
+ secondCondition = false
162
+ myScheduler:runAll()
163
+
164
+ firstCondition = true
165
+ secondCondition = true
166
+ myScheduler:runAll() -- Expect to run
167
+ end)
168
+
169
+ test("yield", function()
170
+ expect.assertions(1)
171
+
172
+ local system = function()
173
+ wait(5)
174
+ end
175
+
176
+ local myPhase = Phase.new("myPhase")
177
+ local myScheduler =
178
+ Scheduler.new(1, 2, 3):insert(myPhase):addSystem(system, myPhase)
179
+
180
+ local err;
181
+
182
+ (myScheduler :: any):_addHook(
183
+ (myScheduler :: any).Hooks.SystemError,
184
+ function(args)
185
+ err = args.error
186
+ end
187
+ )
188
+
189
+ myScheduler:runAll()
190
+ expect(err).toEqual(expect.stringContaining("System yielded"))
191
+ end)
192
+ end)