roblox-opencode 1.0.0 → 1.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.
- package/README.md +112 -122
- package/commands/setup-game.md +108 -108
- package/commands/sync-check.md +53 -53
- package/core/roblox-core.md +93 -93
- package/dist/server.js +189 -167
- package/package.json +35 -35
- package/skills/roblox-analytics/SKILL.md +277 -277
- package/skills/roblox-analytics/references/event-batcher.luau +75 -75
- package/skills/roblox-animation-vfx/SKILL.md +1325 -1325
- package/skills/roblox-architecture/SKILL.md +863 -863
- package/skills/roblox-architecture/references/combat-systems.md +1381 -1381
- package/skills/roblox-code-review/SKILL.md +686 -686
- package/skills/roblox-data/SKILL.md +889 -889
- package/skills/roblox-data/references/inventory-systems.md +1729 -1729
- package/skills/roblox-debug/SKILL.md +98 -98
- package/skills/roblox-gui/SKILL.md +1103 -1103
- package/skills/roblox-gui-fusion/SKILL.md +150 -150
- package/skills/roblox-gui-fusion/references/inventory.luau +427 -427
- package/skills/roblox-gui-fusion/references/settings-menu.luau +579 -579
- package/skills/roblox-gui-fusion/references/shop.luau +411 -411
- package/skills/roblox-luau-mastery/SKILL.md +1519 -1519
- package/skills/roblox-monetization/SKILL.md +1084 -1084
- package/skills/roblox-monetization/references/process-receipt.luau +131 -131
- package/skills/roblox-networking/SKILL.md +669 -669
- package/skills/roblox-networking/references/remote-validator.luau +193 -193
- package/skills/roblox-publish-checklist/SKILL.md +127 -127
- package/skills/roblox-runtime/SKILL.md +753 -753
- package/skills/roblox-sharp-edges/SKILL.md +294 -294
- package/skills/roblox-sync/SKILL.md +126 -126
- package/skills/roblox-testing/SKILL.md +943 -943
- package/skills/roblox-tooling/SKILL.md +149 -149
- package/vendor/LICENSES/ProfileStore-LICENSE +201 -201
- package/vendor/LICENSES/RbxUtil-LICENSE +7 -7
- package/vendor/LICENSES/promise-LICENSE +20 -20
- package/vendor/LICENSES/t-LICENSE +21 -21
- package/vendor/LICENSES/testez-LICENSE +200 -200
- package/vendor/README.md +83 -83
- package/vendor/fusion/Animation/ExternalTime.luau +83 -83
- package/vendor/fusion/Animation/Spring.luau +321 -321
- package/vendor/fusion/Animation/Stopwatch.luau +127 -127
- package/vendor/fusion/Animation/Tween.luau +187 -187
- package/vendor/fusion/Animation/getTweenDuration.luau +27 -27
- package/vendor/fusion/Animation/getTweenRatio.luau +47 -47
- package/vendor/fusion/Animation/lerpType.luau +163 -163
- package/vendor/fusion/Animation/packType.luau +99 -99
- package/vendor/fusion/Animation/springCoefficients.luau +80 -80
- package/vendor/fusion/Animation/unpackType.luau +102 -102
- package/vendor/fusion/Colour/Oklab.luau +70 -70
- package/vendor/fusion/Colour/sRGB.luau +54 -54
- package/vendor/fusion/External.luau +167 -167
- package/vendor/fusion/ExternalDebug.luau +69 -69
- package/vendor/fusion/Graph/Observer.luau +113 -113
- package/vendor/fusion/Graph/castToGraph.luau +28 -28
- package/vendor/fusion/Graph/change.luau +80 -80
- package/vendor/fusion/Graph/depend.luau +32 -32
- package/vendor/fusion/Graph/evaluate.luau +55 -55
- package/vendor/fusion/Instances/Attribute.luau +57 -57
- package/vendor/fusion/Instances/AttributeChange.luau +46 -46
- package/vendor/fusion/Instances/AttributeOut.luau +63 -63
- package/vendor/fusion/Instances/Child.luau +21 -21
- package/vendor/fusion/Instances/Children.luau +147 -147
- package/vendor/fusion/Instances/Hydrate.luau +32 -32
- package/vendor/fusion/Instances/New.luau +52 -52
- package/vendor/fusion/Instances/OnChange.luau +49 -49
- package/vendor/fusion/Instances/OnEvent.luau +53 -53
- package/vendor/fusion/Instances/Out.luau +69 -69
- package/vendor/fusion/Instances/applyInstanceProps.luau +148 -148
- package/vendor/fusion/Instances/defaultProps.luau +194 -194
- package/vendor/fusion/LICENSE +21 -21
- package/vendor/fusion/Logging/formatError.luau +48 -48
- package/vendor/fusion/Logging/messages.luau +51 -51
- package/vendor/fusion/Logging/parseError.luau +24 -24
- package/vendor/fusion/Memory/checkLifetime.luau +133 -133
- package/vendor/fusion/Memory/deriveScope.luau +23 -23
- package/vendor/fusion/Memory/deriveScopeImpl.luau +44 -44
- package/vendor/fusion/Memory/doCleanup.luau +78 -78
- package/vendor/fusion/Memory/innerScope.luau +33 -33
- package/vendor/fusion/Memory/legacyCleanup.luau +17 -17
- package/vendor/fusion/Memory/needsDestruction.luau +16 -16
- package/vendor/fusion/Memory/poisonScope.luau +33 -33
- package/vendor/fusion/Memory/scopePool.luau +54 -54
- package/vendor/fusion/Memory/scoped.luau +26 -26
- package/vendor/fusion/Memory/whichLivesLonger.luau +74 -74
- package/vendor/fusion/RobloxExternal.luau +97 -97
- package/vendor/fusion/State/Computed.luau +138 -138
- package/vendor/fusion/State/For/Disassembly.luau +210 -210
- package/vendor/fusion/State/For/ForTypes.luau +30 -30
- package/vendor/fusion/State/For/init.luau +109 -109
- package/vendor/fusion/State/ForKeys.luau +93 -93
- package/vendor/fusion/State/ForPairs.luau +96 -96
- package/vendor/fusion/State/ForValues.luau +93 -93
- package/vendor/fusion/State/Value.luau +87 -87
- package/vendor/fusion/State/castToState.luau +25 -25
- package/vendor/fusion/State/peek.luau +30 -30
- package/vendor/fusion/Types.luau +314 -314
- package/vendor/fusion/Utility/Contextual.luau +90 -90
- package/vendor/fusion/Utility/Safe.luau +22 -22
- package/vendor/fusion/Utility/isSimilar.luau +29 -29
- package/vendor/fusion/Utility/merge.luau +35 -35
- package/vendor/fusion/Utility/nameOf.luau +34 -34
- package/vendor/fusion/Utility/never.luau +13 -13
- package/vendor/fusion/Utility/nicknames.luau +10 -10
- package/vendor/fusion/Utility/xtypeof.luau +26 -26
- package/vendor/fusion/init.luau +82 -82
- package/vendor/profilestore/init.luau +2242 -2242
- package/vendor/promise/init.luau +1982 -1982
- package/vendor/rbxutil/buffer-util/Buffer.test.luau +25 -25
- package/vendor/rbxutil/buffer-util/BufferReader.luau +228 -228
- package/vendor/rbxutil/buffer-util/BufferWriter.luau +269 -269
- package/vendor/rbxutil/buffer-util/DataTypeBuffer.luau +223 -223
- package/vendor/rbxutil/buffer-util/Types.luau +60 -60
- package/vendor/rbxutil/buffer-util/index.d.ts +153 -153
- package/vendor/rbxutil/buffer-util/init.luau +41 -41
- package/vendor/rbxutil/buffer-util/package.json +16 -16
- package/vendor/rbxutil/buffer-util/wally.toml +9 -9
- package/vendor/rbxutil/comm/Client/ClientComm.luau +232 -232
- package/vendor/rbxutil/comm/Client/ClientRemoteProperty.luau +156 -156
- package/vendor/rbxutil/comm/Client/ClientRemoteSignal.luau +109 -109
- package/vendor/rbxutil/comm/Client/init.luau +135 -135
- package/vendor/rbxutil/comm/Server/RemoteProperty.luau +295 -295
- package/vendor/rbxutil/comm/Server/RemoteSignal.luau +211 -211
- package/vendor/rbxutil/comm/Server/ServerComm.luau +211 -211
- package/vendor/rbxutil/comm/Server/init.luau +140 -140
- package/vendor/rbxutil/comm/Types.luau +18 -18
- package/vendor/rbxutil/comm/Util.luau +27 -27
- package/vendor/rbxutil/comm/init.luau +35 -35
- package/vendor/rbxutil/comm/wally.toml +13 -13
- package/vendor/rbxutil/component/init.luau +759 -759
- package/vendor/rbxutil/component/init.test.luau +311 -311
- package/vendor/rbxutil/component/wally.toml +14 -14
- package/vendor/rbxutil/concur/init.luau +542 -542
- package/vendor/rbxutil/concur/init.test.luau +364 -364
- package/vendor/rbxutil/concur/wally.toml +8 -8
- package/vendor/rbxutil/enum-list/init.luau +101 -101
- package/vendor/rbxutil/enum-list/init.test.luau +91 -91
- package/vendor/rbxutil/enum-list/wally.toml +8 -8
- package/vendor/rbxutil/find/index.d.ts +20 -20
- package/vendor/rbxutil/find/init.luau +44 -44
- package/vendor/rbxutil/find/package.json +17 -17
- package/vendor/rbxutil/find/wally.toml +8 -8
- package/vendor/rbxutil/input/Gamepad.luau +559 -559
- package/vendor/rbxutil/input/Keyboard.luau +124 -124
- package/vendor/rbxutil/input/Mouse.luau +278 -278
- package/vendor/rbxutil/input/PreferredInput.luau +91 -91
- package/vendor/rbxutil/input/Touch.luau +120 -120
- package/vendor/rbxutil/input/init.luau +33 -33
- package/vendor/rbxutil/input/wally.toml +12 -12
- package/vendor/rbxutil/loader/index.d.ts +15 -15
- package/vendor/rbxutil/loader/init.luau +137 -137
- package/vendor/rbxutil/loader/wally.toml +8 -8
- package/vendor/rbxutil/log/index.d.ts +38 -38
- package/vendor/rbxutil/log/init.luau +746 -746
- package/vendor/rbxutil/log/wally.toml +8 -8
- package/vendor/rbxutil/net/init.luau +190 -190
- package/vendor/rbxutil/net/wally.toml +8 -8
- package/vendor/rbxutil/option/index.d.ts +44 -44
- package/vendor/rbxutil/option/init.luau +489 -489
- package/vendor/rbxutil/option/init.test.luau +342 -342
- package/vendor/rbxutil/option/wally.toml +8 -8
- package/vendor/rbxutil/pid/index.d.ts +53 -53
- package/vendor/rbxutil/pid/init.luau +195 -195
- package/vendor/rbxutil/pid/package.json +16 -16
- package/vendor/rbxutil/pid/wally.toml +9 -9
- package/vendor/rbxutil/quaternion/index.d.ts +117 -117
- package/vendor/rbxutil/quaternion/init.luau +570 -570
- package/vendor/rbxutil/quaternion/package.json +16 -16
- package/vendor/rbxutil/quaternion/wally.toml +9 -9
- package/vendor/rbxutil/query/index.d.ts +43 -43
- package/vendor/rbxutil/query/init.luau +117 -117
- package/vendor/rbxutil/query/package.json +18 -18
- package/vendor/rbxutil/query/wally.toml +9 -9
- package/vendor/rbxutil/sequent/index.d.ts +28 -28
- package/vendor/rbxutil/sequent/init.luau +340 -340
- package/vendor/rbxutil/sequent/package.json +16 -16
- package/vendor/rbxutil/sequent/wally.toml +9 -9
- package/vendor/rbxutil/ser/init.luau +175 -175
- package/vendor/rbxutil/ser/init.test.luau +50 -50
- package/vendor/rbxutil/ser/wally.toml +11 -11
- package/vendor/rbxutil/shake/index.d.ts +36 -36
- package/vendor/rbxutil/shake/init.luau +532 -532
- package/vendor/rbxutil/shake/init.test.luau +267 -267
- package/vendor/rbxutil/shake/package.json +16 -16
- package/vendor/rbxutil/shake/wally.toml +9 -9
- package/vendor/rbxutil/signal/index.d.ts +100 -100
- package/vendor/rbxutil/signal/init.luau +432 -432
- package/vendor/rbxutil/signal/init.test.luau +190 -190
- package/vendor/rbxutil/signal/package.json +17 -17
- package/vendor/rbxutil/signal/wally.toml +9 -9
- package/vendor/rbxutil/silo/TableWatcher.luau +65 -65
- package/vendor/rbxutil/silo/Util.luau +55 -55
- package/vendor/rbxutil/silo/init.luau +338 -338
- package/vendor/rbxutil/silo/init.test.luau +215 -215
- package/vendor/rbxutil/silo/wally.toml +8 -8
- package/vendor/rbxutil/spring/index.d.ts +40 -40
- package/vendor/rbxutil/spring/init.luau +97 -97
- package/vendor/rbxutil/spring/package.json +17 -17
- package/vendor/rbxutil/spring/wally.toml +8 -8
- package/vendor/rbxutil/stream/index.d.ts +88 -88
- package/vendor/rbxutil/stream/init.luau +597 -597
- package/vendor/rbxutil/stream/package.json +18 -18
- package/vendor/rbxutil/stream/wally.toml +9 -9
- package/vendor/rbxutil/streamable/Streamable.luau +202 -202
- package/vendor/rbxutil/streamable/StreamableUtil.luau +80 -80
- package/vendor/rbxutil/streamable/init.luau +8 -8
- package/vendor/rbxutil/streamable/wally.toml +12 -12
- package/vendor/rbxutil/symbol/init.luau +56 -56
- package/vendor/rbxutil/symbol/init.test.luau +37 -37
- package/vendor/rbxutil/symbol/wally.toml +8 -8
- package/vendor/rbxutil/table-util/init.luau +938 -938
- package/vendor/rbxutil/table-util/init.test.luau +439 -439
- package/vendor/rbxutil/task-queue/index.d.ts +27 -27
- package/vendor/rbxutil/task-queue/init.luau +97 -97
- package/vendor/rbxutil/task-queue/wally.toml +8 -8
- package/vendor/rbxutil/timer/index.d.ts +81 -81
- package/vendor/rbxutil/timer/init.luau +249 -249
- package/vendor/rbxutil/timer/init.test.luau +73 -73
- package/vendor/rbxutil/timer/wally.toml +11 -11
- package/vendor/rbxutil/tree/index.d.ts +15 -15
- package/vendor/rbxutil/tree/init.luau +137 -137
- package/vendor/rbxutil/tree/wally.toml +8 -8
- package/vendor/rbxutil/trove/index.d.ts +46 -46
- package/vendor/rbxutil/trove/init.luau +787 -787
- package/vendor/rbxutil/trove/init.test.luau +203 -203
- package/vendor/rbxutil/trove/wally.toml +8 -8
- package/vendor/rbxutil/typed-remote/init.luau +196 -196
- package/vendor/rbxutil/typed-remote/wally.toml +8 -8
- package/vendor/rbxutil/wait-for/index.d.ts +17 -17
- package/vendor/rbxutil/wait-for/init.luau +257 -257
- package/vendor/rbxutil/wait-for/init.test.luau +182 -182
- package/vendor/rbxutil/wait-for/wally.toml +11 -11
- package/vendor/t/t.lua +1350 -1350
- package/vendor/testez/Context.lua +26 -26
- package/vendor/testez/Expectation.lua +311 -311
- package/vendor/testez/ExpectationContext.lua +38 -38
- package/vendor/testez/LifecycleHooks.lua +89 -89
- package/vendor/testez/Reporters/TeamCityReporter.lua +101 -101
- package/vendor/testez/Reporters/TextReporter.lua +105 -105
- package/vendor/testez/Reporters/TextReporterQuiet.lua +96 -96
- package/vendor/testez/TestBootstrap.lua +146 -146
- package/vendor/testez/TestEnum.lua +27 -27
- package/vendor/testez/TestPlan.lua +304 -304
- package/vendor/testez/TestPlanner.lua +39 -39
- package/vendor/testez/TestResults.lua +111 -111
- package/vendor/testez/TestRunner.lua +188 -188
- package/vendor/testez/TestSession.lua +243 -243
- package/vendor/testez/init.lua +39 -39
|
@@ -1,311 +1,311 @@
|
|
|
1
|
-
local CollectionService = game:GetService("CollectionService")
|
|
2
|
-
local RunService = game:GetService("RunService")
|
|
3
|
-
local ServerScriptService = game:GetService("ServerScriptService")
|
|
4
|
-
|
|
5
|
-
local Test = require(ServerScriptService.TestRunner.Test)
|
|
6
|
-
|
|
7
|
-
return function(ctx: Test.TestContext)
|
|
8
|
-
local Component = require(script.Parent)
|
|
9
|
-
|
|
10
|
-
local TAG = "__KnitTestComponent__"
|
|
11
|
-
|
|
12
|
-
local taggedInstanceFolder
|
|
13
|
-
|
|
14
|
-
local function CreateTaggedInstance()
|
|
15
|
-
local folder = Instance.new("Folder")
|
|
16
|
-
CollectionService:AddTag(folder, TAG)
|
|
17
|
-
folder.Name = "ComponentTest"
|
|
18
|
-
folder.Archivable = false
|
|
19
|
-
folder.Parent = taggedInstanceFolder
|
|
20
|
-
return folder
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
local ExtensionTest = {}
|
|
24
|
-
function ExtensionTest.ShouldConstruct(_component)
|
|
25
|
-
return true
|
|
26
|
-
end
|
|
27
|
-
function ExtensionTest.Constructing(component)
|
|
28
|
-
component.Data = "a"
|
|
29
|
-
component.DidHeartbeat = false
|
|
30
|
-
component.DidStepped = false
|
|
31
|
-
component.DidRenderStepped = false
|
|
32
|
-
end
|
|
33
|
-
function ExtensionTest.Constructed(component)
|
|
34
|
-
component.Data ..= "c"
|
|
35
|
-
end
|
|
36
|
-
function ExtensionTest.Starting(component)
|
|
37
|
-
component.Data ..= "d"
|
|
38
|
-
end
|
|
39
|
-
function ExtensionTest.Started(component)
|
|
40
|
-
component.Data ..= "f"
|
|
41
|
-
end
|
|
42
|
-
function ExtensionTest.Stopping(component)
|
|
43
|
-
component.Data ..= "g"
|
|
44
|
-
end
|
|
45
|
-
function ExtensionTest.Stopped(component)
|
|
46
|
-
component.Data ..= "i"
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
local TestComponentMain = Component.new({
|
|
50
|
-
Tag = TAG,
|
|
51
|
-
Ancestors = { workspace, game:GetService("Lighting") },
|
|
52
|
-
Extensions = { ExtensionTest },
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
local AnotherComponent = Component.new({ Tag = TAG })
|
|
56
|
-
function AnotherComponent:GetData()
|
|
57
|
-
return true
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
function TestComponentMain:Construct()
|
|
61
|
-
self.Data ..= "b"
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
function TestComponentMain:Start()
|
|
65
|
-
self.Another = self:GetComponent(AnotherComponent)
|
|
66
|
-
self.Data ..= "e"
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
function TestComponentMain:Stop()
|
|
70
|
-
self.Data ..= "h"
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
function TestComponentMain:HeartbeatUpdate(_dt)
|
|
74
|
-
self.DidHeartbeat = true
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
function TestComponentMain:SteppedUpdate(_dt)
|
|
78
|
-
self.DidStepped = true
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
function TestComponentMain:RenderSteppedUpdate(_dt)
|
|
82
|
-
self.DidRenderStepped = true
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
ctx:BeforeAll(function()
|
|
86
|
-
taggedInstanceFolder = Instance.new("Folder")
|
|
87
|
-
taggedInstanceFolder.Name = "KnitComponentTest"
|
|
88
|
-
taggedInstanceFolder.Archivable = false
|
|
89
|
-
taggedInstanceFolder.Parent = workspace
|
|
90
|
-
end)
|
|
91
|
-
|
|
92
|
-
ctx:AfterAll(function()
|
|
93
|
-
taggedInstanceFolder:Destroy()
|
|
94
|
-
TestComponentMain:Destroy()
|
|
95
|
-
end)
|
|
96
|
-
|
|
97
|
-
ctx:Describe("Component", function()
|
|
98
|
-
ctx:AfterEach(function()
|
|
99
|
-
taggedInstanceFolder:ClearAllChildren()
|
|
100
|
-
end)
|
|
101
|
-
|
|
102
|
-
ctx:Test("should capture start and stop events", function()
|
|
103
|
-
local didStart = 0
|
|
104
|
-
local didStop = 0
|
|
105
|
-
local started = TestComponentMain.Started:Connect(function()
|
|
106
|
-
didStart += 1
|
|
107
|
-
end)
|
|
108
|
-
local stopped = TestComponentMain.Stopped:Connect(function()
|
|
109
|
-
didStop += 1
|
|
110
|
-
end)
|
|
111
|
-
local instance = CreateTaggedInstance()
|
|
112
|
-
task.wait()
|
|
113
|
-
instance:Destroy()
|
|
114
|
-
task.wait()
|
|
115
|
-
started:Disconnect()
|
|
116
|
-
stopped:Disconnect()
|
|
117
|
-
ctx:Expect(didStart):ToBe(1)
|
|
118
|
-
ctx:Expect(didStop):ToBe(1)
|
|
119
|
-
end)
|
|
120
|
-
|
|
121
|
-
ctx:Test("should be able to get component from the instance", function()
|
|
122
|
-
local instance = CreateTaggedInstance()
|
|
123
|
-
task.wait()
|
|
124
|
-
local component = TestComponentMain:FromInstance(instance)
|
|
125
|
-
ctx:Expect(component):ToBeOk()
|
|
126
|
-
end)
|
|
127
|
-
|
|
128
|
-
ctx:Test("should be able to get all component instances existing", function()
|
|
129
|
-
local numComponents = 3
|
|
130
|
-
local instances = table.create(numComponents)
|
|
131
|
-
for i = 1, numComponents do
|
|
132
|
-
local instance = CreateTaggedInstance()
|
|
133
|
-
instances[i] = instance
|
|
134
|
-
end
|
|
135
|
-
task.wait()
|
|
136
|
-
local components = TestComponentMain:GetAll()
|
|
137
|
-
ctx:Expect(components):ToBeA("table")
|
|
138
|
-
ctx:Expect(components):ToHaveLength(numComponents)
|
|
139
|
-
for _, c in components do
|
|
140
|
-
ctx:Expect(table.find(instances, c.Instance)):ToBeOk()
|
|
141
|
-
end
|
|
142
|
-
end)
|
|
143
|
-
|
|
144
|
-
ctx:Test("should call lifecycle methods and extension functions", function()
|
|
145
|
-
local instance = CreateTaggedInstance()
|
|
146
|
-
task.wait(0.2)
|
|
147
|
-
local component = TestComponentMain:FromInstance(instance)
|
|
148
|
-
ctx:Expect(component):ToBeOk()
|
|
149
|
-
ctx:Expect(component.Data):ToBe("abcdef")
|
|
150
|
-
ctx:Expect(component.DidHeartbeat):ToBe(true)
|
|
151
|
-
ctx:Expect(component.DidStepped):ToBe(RunService:IsRunning())
|
|
152
|
-
ctx:Expect(component.DidRenderStepped):Not():ToBe(true)
|
|
153
|
-
instance:Destroy()
|
|
154
|
-
task.wait()
|
|
155
|
-
ctx:Expect(component.Data):ToBe("abcdefghi")
|
|
156
|
-
end)
|
|
157
|
-
|
|
158
|
-
ctx:Test("should get another component linked to the same instance", function()
|
|
159
|
-
local instance = CreateTaggedInstance()
|
|
160
|
-
task.wait()
|
|
161
|
-
local component = TestComponentMain:FromInstance(instance)
|
|
162
|
-
ctx:Expect(component):ToBeOk()
|
|
163
|
-
ctx:Expect(component.Another):ToBeOk()
|
|
164
|
-
ctx:Expect(component.Another:GetData()):ToBe(true)
|
|
165
|
-
end)
|
|
166
|
-
|
|
167
|
-
ctx:Test("should use extension to decide whether or not to construct", function()
|
|
168
|
-
local e1 = { c = true }
|
|
169
|
-
function e1.ShouldConstruct(_component)
|
|
170
|
-
return e1.c
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
local e2 = { c = true }
|
|
174
|
-
function e2.ShouldConstruct(_component)
|
|
175
|
-
return e2.c
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
local e3 = { c = true }
|
|
179
|
-
function e3.ShouldConstruct(_component)
|
|
180
|
-
return e3.c
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
local c1 = Component.new({ Tag = TAG, Extensions = { e1 } })
|
|
184
|
-
local c2 = Component.new({ Tag = TAG, Extensions = { e1, e2 } })
|
|
185
|
-
local c3 = Component.new({ Tag = TAG, Extensions = { e1, e2, e3 } })
|
|
186
|
-
|
|
187
|
-
local function SetE(a, b, c)
|
|
188
|
-
e1.c = a
|
|
189
|
-
e2.c = b
|
|
190
|
-
e3.c = c
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
local function Check(inst, comp, shouldExist)
|
|
194
|
-
local c = comp:FromInstance(inst)
|
|
195
|
-
if shouldExist then
|
|
196
|
-
ctx:Expect(c):ToBeOk()
|
|
197
|
-
else
|
|
198
|
-
ctx:Expect(c):ToBeNil()
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
local function CreateAndCheckAll(a, b, c)
|
|
203
|
-
local instance = CreateTaggedInstance()
|
|
204
|
-
task.wait()
|
|
205
|
-
Check(instance, c1, a)
|
|
206
|
-
Check(instance, c2, b)
|
|
207
|
-
Check(instance, c3, c)
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
-- All green:
|
|
211
|
-
SetE(true, true, true)
|
|
212
|
-
CreateAndCheckAll(true, true, true)
|
|
213
|
-
|
|
214
|
-
-- All red:
|
|
215
|
-
SetE(false, false, false)
|
|
216
|
-
CreateAndCheckAll(false, false, false)
|
|
217
|
-
|
|
218
|
-
-- One red:
|
|
219
|
-
SetE(true, false, true)
|
|
220
|
-
CreateAndCheckAll(true, false, false)
|
|
221
|
-
|
|
222
|
-
-- One green:
|
|
223
|
-
SetE(false, false, true)
|
|
224
|
-
CreateAndCheckAll(false, false, false)
|
|
225
|
-
end)
|
|
226
|
-
|
|
227
|
-
ctx:Test("should decide whether or not to use extend", function()
|
|
228
|
-
local e1 = { extend = true }
|
|
229
|
-
function e1.ShouldExtend(_component)
|
|
230
|
-
return e1.extend
|
|
231
|
-
end
|
|
232
|
-
function e1.Constructing(component)
|
|
233
|
-
component.E1 = true
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
local e2 = { extend = true }
|
|
237
|
-
function e2.ShouldExtend(_component)
|
|
238
|
-
return e2.extend
|
|
239
|
-
end
|
|
240
|
-
function e2.Constructing(component)
|
|
241
|
-
component.E2 = true
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
local TestComponent = Component.new({ Tag = TAG, Extensions = { e1, e2 } })
|
|
245
|
-
|
|
246
|
-
local function SetAndCheck(ex1, ex2)
|
|
247
|
-
e1.extend = ex1
|
|
248
|
-
e2.extend = ex2
|
|
249
|
-
local instance = CreateTaggedInstance()
|
|
250
|
-
task.wait()
|
|
251
|
-
local component = TestComponent:FromInstance(instance)
|
|
252
|
-
ctx:Expect(component):ToBeOk()
|
|
253
|
-
if ex1 then
|
|
254
|
-
ctx:Expect(component.E1):ToBe(true)
|
|
255
|
-
else
|
|
256
|
-
ctx:Expect(component.E1):ToBeNil()
|
|
257
|
-
end
|
|
258
|
-
if ex2 then
|
|
259
|
-
ctx:Expect(component.E2):ToBe(true)
|
|
260
|
-
else
|
|
261
|
-
ctx:Expect(component.E2):ToBeNil()
|
|
262
|
-
end
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
SetAndCheck(true, true)
|
|
266
|
-
SetAndCheck(false, false)
|
|
267
|
-
SetAndCheck(true, false)
|
|
268
|
-
SetAndCheck(false, true)
|
|
269
|
-
end)
|
|
270
|
-
|
|
271
|
-
ctx:Test("should allow yielding within construct", function()
|
|
272
|
-
local CUSTOM_TAG = "CustomTag"
|
|
273
|
-
|
|
274
|
-
local TestComponent = Component.new({ Tag = CUSTOM_TAG })
|
|
275
|
-
|
|
276
|
-
local numConstruct = 0
|
|
277
|
-
|
|
278
|
-
function TestComponent:Construct()
|
|
279
|
-
numConstruct += 1
|
|
280
|
-
task.wait(0.5)
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
local p = Instance.new("Part")
|
|
284
|
-
p.Anchored = true
|
|
285
|
-
p.Parent = game:GetService("ReplicatedStorage")
|
|
286
|
-
CollectionService:AddTag(p, CUSTOM_TAG)
|
|
287
|
-
local newP = p:Clone()
|
|
288
|
-
newP.Parent = workspace
|
|
289
|
-
|
|
290
|
-
task.wait(0.6)
|
|
291
|
-
|
|
292
|
-
ctx:Expect(numConstruct):ToBe(1)
|
|
293
|
-
p:Destroy()
|
|
294
|
-
newP:Destroy()
|
|
295
|
-
end)
|
|
296
|
-
|
|
297
|
-
ctx:Test("should wait for instance", function()
|
|
298
|
-
local p = Instance.new("Part")
|
|
299
|
-
p.Anchored = true
|
|
300
|
-
p.Parent = workspace
|
|
301
|
-
task.delay(0.1, function()
|
|
302
|
-
CollectionService:AddTag(p, TAG)
|
|
303
|
-
end)
|
|
304
|
-
local success, c = TestComponentMain:WaitForInstance(p):timeout(1):await()
|
|
305
|
-
ctx:Expect(success):ToBe(true)
|
|
306
|
-
ctx:Expect(c):ToBeA("table")
|
|
307
|
-
ctx:Expect(c.Instance):ToBe(p)
|
|
308
|
-
p:Destroy()
|
|
309
|
-
end)
|
|
310
|
-
end)
|
|
311
|
-
end
|
|
1
|
+
local CollectionService = game:GetService("CollectionService")
|
|
2
|
+
local RunService = game:GetService("RunService")
|
|
3
|
+
local ServerScriptService = game:GetService("ServerScriptService")
|
|
4
|
+
|
|
5
|
+
local Test = require(ServerScriptService.TestRunner.Test)
|
|
6
|
+
|
|
7
|
+
return function(ctx: Test.TestContext)
|
|
8
|
+
local Component = require(script.Parent)
|
|
9
|
+
|
|
10
|
+
local TAG = "__KnitTestComponent__"
|
|
11
|
+
|
|
12
|
+
local taggedInstanceFolder
|
|
13
|
+
|
|
14
|
+
local function CreateTaggedInstance()
|
|
15
|
+
local folder = Instance.new("Folder")
|
|
16
|
+
CollectionService:AddTag(folder, TAG)
|
|
17
|
+
folder.Name = "ComponentTest"
|
|
18
|
+
folder.Archivable = false
|
|
19
|
+
folder.Parent = taggedInstanceFolder
|
|
20
|
+
return folder
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
local ExtensionTest = {}
|
|
24
|
+
function ExtensionTest.ShouldConstruct(_component)
|
|
25
|
+
return true
|
|
26
|
+
end
|
|
27
|
+
function ExtensionTest.Constructing(component)
|
|
28
|
+
component.Data = "a"
|
|
29
|
+
component.DidHeartbeat = false
|
|
30
|
+
component.DidStepped = false
|
|
31
|
+
component.DidRenderStepped = false
|
|
32
|
+
end
|
|
33
|
+
function ExtensionTest.Constructed(component)
|
|
34
|
+
component.Data ..= "c"
|
|
35
|
+
end
|
|
36
|
+
function ExtensionTest.Starting(component)
|
|
37
|
+
component.Data ..= "d"
|
|
38
|
+
end
|
|
39
|
+
function ExtensionTest.Started(component)
|
|
40
|
+
component.Data ..= "f"
|
|
41
|
+
end
|
|
42
|
+
function ExtensionTest.Stopping(component)
|
|
43
|
+
component.Data ..= "g"
|
|
44
|
+
end
|
|
45
|
+
function ExtensionTest.Stopped(component)
|
|
46
|
+
component.Data ..= "i"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
local TestComponentMain = Component.new({
|
|
50
|
+
Tag = TAG,
|
|
51
|
+
Ancestors = { workspace, game:GetService("Lighting") },
|
|
52
|
+
Extensions = { ExtensionTest },
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
local AnotherComponent = Component.new({ Tag = TAG })
|
|
56
|
+
function AnotherComponent:GetData()
|
|
57
|
+
return true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
function TestComponentMain:Construct()
|
|
61
|
+
self.Data ..= "b"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
function TestComponentMain:Start()
|
|
65
|
+
self.Another = self:GetComponent(AnotherComponent)
|
|
66
|
+
self.Data ..= "e"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
function TestComponentMain:Stop()
|
|
70
|
+
self.Data ..= "h"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
function TestComponentMain:HeartbeatUpdate(_dt)
|
|
74
|
+
self.DidHeartbeat = true
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
function TestComponentMain:SteppedUpdate(_dt)
|
|
78
|
+
self.DidStepped = true
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
function TestComponentMain:RenderSteppedUpdate(_dt)
|
|
82
|
+
self.DidRenderStepped = true
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
ctx:BeforeAll(function()
|
|
86
|
+
taggedInstanceFolder = Instance.new("Folder")
|
|
87
|
+
taggedInstanceFolder.Name = "KnitComponentTest"
|
|
88
|
+
taggedInstanceFolder.Archivable = false
|
|
89
|
+
taggedInstanceFolder.Parent = workspace
|
|
90
|
+
end)
|
|
91
|
+
|
|
92
|
+
ctx:AfterAll(function()
|
|
93
|
+
taggedInstanceFolder:Destroy()
|
|
94
|
+
TestComponentMain:Destroy()
|
|
95
|
+
end)
|
|
96
|
+
|
|
97
|
+
ctx:Describe("Component", function()
|
|
98
|
+
ctx:AfterEach(function()
|
|
99
|
+
taggedInstanceFolder:ClearAllChildren()
|
|
100
|
+
end)
|
|
101
|
+
|
|
102
|
+
ctx:Test("should capture start and stop events", function()
|
|
103
|
+
local didStart = 0
|
|
104
|
+
local didStop = 0
|
|
105
|
+
local started = TestComponentMain.Started:Connect(function()
|
|
106
|
+
didStart += 1
|
|
107
|
+
end)
|
|
108
|
+
local stopped = TestComponentMain.Stopped:Connect(function()
|
|
109
|
+
didStop += 1
|
|
110
|
+
end)
|
|
111
|
+
local instance = CreateTaggedInstance()
|
|
112
|
+
task.wait()
|
|
113
|
+
instance:Destroy()
|
|
114
|
+
task.wait()
|
|
115
|
+
started:Disconnect()
|
|
116
|
+
stopped:Disconnect()
|
|
117
|
+
ctx:Expect(didStart):ToBe(1)
|
|
118
|
+
ctx:Expect(didStop):ToBe(1)
|
|
119
|
+
end)
|
|
120
|
+
|
|
121
|
+
ctx:Test("should be able to get component from the instance", function()
|
|
122
|
+
local instance = CreateTaggedInstance()
|
|
123
|
+
task.wait()
|
|
124
|
+
local component = TestComponentMain:FromInstance(instance)
|
|
125
|
+
ctx:Expect(component):ToBeOk()
|
|
126
|
+
end)
|
|
127
|
+
|
|
128
|
+
ctx:Test("should be able to get all component instances existing", function()
|
|
129
|
+
local numComponents = 3
|
|
130
|
+
local instances = table.create(numComponents)
|
|
131
|
+
for i = 1, numComponents do
|
|
132
|
+
local instance = CreateTaggedInstance()
|
|
133
|
+
instances[i] = instance
|
|
134
|
+
end
|
|
135
|
+
task.wait()
|
|
136
|
+
local components = TestComponentMain:GetAll()
|
|
137
|
+
ctx:Expect(components):ToBeA("table")
|
|
138
|
+
ctx:Expect(components):ToHaveLength(numComponents)
|
|
139
|
+
for _, c in components do
|
|
140
|
+
ctx:Expect(table.find(instances, c.Instance)):ToBeOk()
|
|
141
|
+
end
|
|
142
|
+
end)
|
|
143
|
+
|
|
144
|
+
ctx:Test("should call lifecycle methods and extension functions", function()
|
|
145
|
+
local instance = CreateTaggedInstance()
|
|
146
|
+
task.wait(0.2)
|
|
147
|
+
local component = TestComponentMain:FromInstance(instance)
|
|
148
|
+
ctx:Expect(component):ToBeOk()
|
|
149
|
+
ctx:Expect(component.Data):ToBe("abcdef")
|
|
150
|
+
ctx:Expect(component.DidHeartbeat):ToBe(true)
|
|
151
|
+
ctx:Expect(component.DidStepped):ToBe(RunService:IsRunning())
|
|
152
|
+
ctx:Expect(component.DidRenderStepped):Not():ToBe(true)
|
|
153
|
+
instance:Destroy()
|
|
154
|
+
task.wait()
|
|
155
|
+
ctx:Expect(component.Data):ToBe("abcdefghi")
|
|
156
|
+
end)
|
|
157
|
+
|
|
158
|
+
ctx:Test("should get another component linked to the same instance", function()
|
|
159
|
+
local instance = CreateTaggedInstance()
|
|
160
|
+
task.wait()
|
|
161
|
+
local component = TestComponentMain:FromInstance(instance)
|
|
162
|
+
ctx:Expect(component):ToBeOk()
|
|
163
|
+
ctx:Expect(component.Another):ToBeOk()
|
|
164
|
+
ctx:Expect(component.Another:GetData()):ToBe(true)
|
|
165
|
+
end)
|
|
166
|
+
|
|
167
|
+
ctx:Test("should use extension to decide whether or not to construct", function()
|
|
168
|
+
local e1 = { c = true }
|
|
169
|
+
function e1.ShouldConstruct(_component)
|
|
170
|
+
return e1.c
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
local e2 = { c = true }
|
|
174
|
+
function e2.ShouldConstruct(_component)
|
|
175
|
+
return e2.c
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
local e3 = { c = true }
|
|
179
|
+
function e3.ShouldConstruct(_component)
|
|
180
|
+
return e3.c
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
local c1 = Component.new({ Tag = TAG, Extensions = { e1 } })
|
|
184
|
+
local c2 = Component.new({ Tag = TAG, Extensions = { e1, e2 } })
|
|
185
|
+
local c3 = Component.new({ Tag = TAG, Extensions = { e1, e2, e3 } })
|
|
186
|
+
|
|
187
|
+
local function SetE(a, b, c)
|
|
188
|
+
e1.c = a
|
|
189
|
+
e2.c = b
|
|
190
|
+
e3.c = c
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
local function Check(inst, comp, shouldExist)
|
|
194
|
+
local c = comp:FromInstance(inst)
|
|
195
|
+
if shouldExist then
|
|
196
|
+
ctx:Expect(c):ToBeOk()
|
|
197
|
+
else
|
|
198
|
+
ctx:Expect(c):ToBeNil()
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
local function CreateAndCheckAll(a, b, c)
|
|
203
|
+
local instance = CreateTaggedInstance()
|
|
204
|
+
task.wait()
|
|
205
|
+
Check(instance, c1, a)
|
|
206
|
+
Check(instance, c2, b)
|
|
207
|
+
Check(instance, c3, c)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
-- All green:
|
|
211
|
+
SetE(true, true, true)
|
|
212
|
+
CreateAndCheckAll(true, true, true)
|
|
213
|
+
|
|
214
|
+
-- All red:
|
|
215
|
+
SetE(false, false, false)
|
|
216
|
+
CreateAndCheckAll(false, false, false)
|
|
217
|
+
|
|
218
|
+
-- One red:
|
|
219
|
+
SetE(true, false, true)
|
|
220
|
+
CreateAndCheckAll(true, false, false)
|
|
221
|
+
|
|
222
|
+
-- One green:
|
|
223
|
+
SetE(false, false, true)
|
|
224
|
+
CreateAndCheckAll(false, false, false)
|
|
225
|
+
end)
|
|
226
|
+
|
|
227
|
+
ctx:Test("should decide whether or not to use extend", function()
|
|
228
|
+
local e1 = { extend = true }
|
|
229
|
+
function e1.ShouldExtend(_component)
|
|
230
|
+
return e1.extend
|
|
231
|
+
end
|
|
232
|
+
function e1.Constructing(component)
|
|
233
|
+
component.E1 = true
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
local e2 = { extend = true }
|
|
237
|
+
function e2.ShouldExtend(_component)
|
|
238
|
+
return e2.extend
|
|
239
|
+
end
|
|
240
|
+
function e2.Constructing(component)
|
|
241
|
+
component.E2 = true
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
local TestComponent = Component.new({ Tag = TAG, Extensions = { e1, e2 } })
|
|
245
|
+
|
|
246
|
+
local function SetAndCheck(ex1, ex2)
|
|
247
|
+
e1.extend = ex1
|
|
248
|
+
e2.extend = ex2
|
|
249
|
+
local instance = CreateTaggedInstance()
|
|
250
|
+
task.wait()
|
|
251
|
+
local component = TestComponent:FromInstance(instance)
|
|
252
|
+
ctx:Expect(component):ToBeOk()
|
|
253
|
+
if ex1 then
|
|
254
|
+
ctx:Expect(component.E1):ToBe(true)
|
|
255
|
+
else
|
|
256
|
+
ctx:Expect(component.E1):ToBeNil()
|
|
257
|
+
end
|
|
258
|
+
if ex2 then
|
|
259
|
+
ctx:Expect(component.E2):ToBe(true)
|
|
260
|
+
else
|
|
261
|
+
ctx:Expect(component.E2):ToBeNil()
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
SetAndCheck(true, true)
|
|
266
|
+
SetAndCheck(false, false)
|
|
267
|
+
SetAndCheck(true, false)
|
|
268
|
+
SetAndCheck(false, true)
|
|
269
|
+
end)
|
|
270
|
+
|
|
271
|
+
ctx:Test("should allow yielding within construct", function()
|
|
272
|
+
local CUSTOM_TAG = "CustomTag"
|
|
273
|
+
|
|
274
|
+
local TestComponent = Component.new({ Tag = CUSTOM_TAG })
|
|
275
|
+
|
|
276
|
+
local numConstruct = 0
|
|
277
|
+
|
|
278
|
+
function TestComponent:Construct()
|
|
279
|
+
numConstruct += 1
|
|
280
|
+
task.wait(0.5)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
local p = Instance.new("Part")
|
|
284
|
+
p.Anchored = true
|
|
285
|
+
p.Parent = game:GetService("ReplicatedStorage")
|
|
286
|
+
CollectionService:AddTag(p, CUSTOM_TAG)
|
|
287
|
+
local newP = p:Clone()
|
|
288
|
+
newP.Parent = workspace
|
|
289
|
+
|
|
290
|
+
task.wait(0.6)
|
|
291
|
+
|
|
292
|
+
ctx:Expect(numConstruct):ToBe(1)
|
|
293
|
+
p:Destroy()
|
|
294
|
+
newP:Destroy()
|
|
295
|
+
end)
|
|
296
|
+
|
|
297
|
+
ctx:Test("should wait for instance", function()
|
|
298
|
+
local p = Instance.new("Part")
|
|
299
|
+
p.Anchored = true
|
|
300
|
+
p.Parent = workspace
|
|
301
|
+
task.delay(0.1, function()
|
|
302
|
+
CollectionService:AddTag(p, TAG)
|
|
303
|
+
end)
|
|
304
|
+
local success, c = TestComponentMain:WaitForInstance(p):timeout(1):await()
|
|
305
|
+
ctx:Expect(success):ToBe(true)
|
|
306
|
+
ctx:Expect(c):ToBeA("table")
|
|
307
|
+
ctx:Expect(c.Instance):ToBe(p)
|
|
308
|
+
p:Destroy()
|
|
309
|
+
end)
|
|
310
|
+
end)
|
|
311
|
+
end
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "sleitnick/component"
|
|
3
|
-
description = "Component class"
|
|
4
|
-
version = "2.4.8"
|
|
5
|
-
license = "MIT"
|
|
6
|
-
authors = ["Stephen Leitnick"]
|
|
7
|
-
registry = "https://github.com/UpliftGames/wally-index"
|
|
8
|
-
realm = "shared"
|
|
9
|
-
|
|
10
|
-
[dependencies]
|
|
11
|
-
Signal = "sleitnick/signal@^2"
|
|
12
|
-
Symbol = "sleitnick/symbol@^2"
|
|
13
|
-
Trove = "sleitnick/trove@^1"
|
|
14
|
-
Promise = "evaera/promise@^4"
|
|
1
|
+
[package]
|
|
2
|
+
name = "sleitnick/component"
|
|
3
|
+
description = "Component class"
|
|
4
|
+
version = "2.4.8"
|
|
5
|
+
license = "MIT"
|
|
6
|
+
authors = ["Stephen Leitnick"]
|
|
7
|
+
registry = "https://github.com/UpliftGames/wally-index"
|
|
8
|
+
realm = "shared"
|
|
9
|
+
|
|
10
|
+
[dependencies]
|
|
11
|
+
Signal = "sleitnick/signal@^2"
|
|
12
|
+
Symbol = "sleitnick/symbol@^2"
|
|
13
|
+
Trove = "sleitnick/trove@^1"
|
|
14
|
+
Promise = "evaera/promise@^4"
|