chore: housekeeping

This commit is contained in:
littensy 2025-05-21 12:16:29 -07:00
parent 4931515a95
commit 4edc952c05
77 changed files with 230 additions and 602 deletions

4
.gitignore vendored
View file

@ -1,9 +1,9 @@
/.vscode
/.pesde
/build
/DevPackages
/pkgs/**/wally.lock
/packages/**/wally.lock
/sourcemap.json
node_modules
*.tsbuildinfo
*.rbxm
.DS_Store

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "test/suite"]
path = test/suite
url = https://gist.github.com/littensy/fa9afcc5d66d25e86538634982be4ee4

View file

@ -5,6 +5,6 @@
},
"aliases": {
"test": "test",
"pkgs": "pkgs"
"packages": "packages"
}
}

1
.npmrc Normal file
View file

@ -0,0 +1 @@
public-hoist-pattern[]=*@rbxts*

View file

@ -1,4 +1,4 @@
local Charm = require("@pkgs/charm/src/lib")
local Charm = require("@packages/charm/src")
local bench = require("./bench")
local atom = Charm.atom

View file

@ -1,4 +1,4 @@
local Charm = require("@pkgs/charm/src/lib")
local Charm = require("@packages/charm/src")
local bench = require("./bench")
local signals = Charm.signals

View file

@ -1,5 +1,5 @@
mkdir build
rojo build pkgs/charm -o build/charm.rbxm
rojo build pkgs/charm-sync -o build/charm-sync.rbxm
rojo build pkgs/react-charm -o build/react-charm.rbxm
rojo build pkgs/vide-charm -o build/vide-charm.rbxm
rojo build packages/charm -o build/charm.rbxm
rojo build packages/charm-sync -o build/charm-sync.rbxm
rojo build packages/react-charm -o build/react-charm.rbxm
rojo build packages/vide-charm -o build/vide-charm.rbxm

View file

@ -6,11 +6,11 @@ luau-lsp analyze \
--defs=bin/roblox.d.luau \
--flag:LuauFixIndexerSubtypingOrdering=true \
--sourcemap=sourcemap.json \
--ignore="**/_Index/**" \
pkgs test
--ignore="**/node_modules/**" \
packages test
selene pkgs test
selene packages test
stylua --check pkgs test
stylua --check packages test
rm bin/roblox.d.luau

View file

@ -5,21 +5,22 @@
"ReplicatedStorage": {
"$className": "ReplicatedStorage",
"Packages": {
"$path": "DevPackages",
"Charm": { "$path": "pkgs/charm" },
"CharmSync": { "$path": "pkgs/charm-sync" },
"ReactCharm": { "$path": "pkgs/react-charm" },
"VideCharm": { "$path": "pkgs/vide-charm" }
"$path": "node_modules/@rbxts-js",
"Vide": { "$path": "node_modules/@rbxts/vide/src" },
"Charm": { "$path": "packages/charm" },
"CharmSync": { "$path": "packages/charm-sync" },
"ReactCharm": { "$path": "packages/react-charm" },
"VideCharm": { "$path": "packages/vide-charm" }
}
},
"ServerScriptService": {
"$className": "ServerScriptService",
"Tests": {
"$path": "test",
"Charm": { "$path": "pkgs/charm/tests" },
"CharmSync": { "$path": "pkgs/charm-sync/tests" },
"ReactCharm": { "$path": "pkgs/react-charm/tests" },
"VideCharm": { "$path": "pkgs/vide-charm/tests" }
"Charm": { "$path": "packages/charm/tests" },
"CharmSync": { "$path": "packages/charm-sync/tests" },
"ReactCharm": { "$path": "packages/react-charm/tests" },
"VideCharm": { "$path": "packages/vide-charm/tests" }
},
"Benchmarks": {
"$path": "benches"

14
package.json Normal file
View file

@ -0,0 +1,14 @@
{
"private": true,
"scripts": {
"test": "lute test/init.luau",
"build": "sh bin/build.sh",
"typecheck": "sh bin/check.sh"
},
"packageManager": "pnpm@10.11.0",
"devDependencies": {
"@rbxts-js/react": "17.1.20-ts.1",
"@rbxts-js/react-roblox": "17.1.20-ts.1",
"@rbxts/vide": "^0.5.7"
}
}

View file

@ -7,7 +7,7 @@ local endBatch = signals.endBatch
local function handleBatched(ok: boolean, ...)
endBatch()
if not ok then
if ok then
return ...
else
error(...)

View file

@ -1,14 +1,14 @@
local atom = require("./atom")
local batched = require("./batched")
local effect = require("./effect")
local listen = require("./listen")
local mapped = require("./mapped")
local observe = require("./observe")
local onCleanup = require("./onCleanup")
local signals = require("./signals")
local subscribe = require("./subscribe")
local types = require("./types")
local untracked = require("./untracked")
local atom = require("@self/atom")
local batched = require("@self/batched")
local effect = require("@self/effect")
local listen = require("@self/listen")
local mapped = require("@self/mapped")
local observe = require("@self/observe")
local onCleanup = require("@self/onCleanup")
local signals = require("@self/signals")
local subscribe = require("@self/subscribe")
local types = require("@self/types")
local untracked = require("@self/untracked")
export type Atom<T = any> = types.Atom<T>
export type Getter<T = any> = types.Getter<T>

View file

@ -1,4 +1,4 @@
local Charm = require("../src/lib")
local Charm = require("../src")
local suite = require("@test/suite")
local atom = Charm.atom

View file

@ -1,4 +1,4 @@
local Charm = require("../src/lib")
local Charm = require("../src")
local suite = require("@test/suite")
local atom = Charm.atom

View file

@ -1,4 +1,4 @@
local Charm = require("../src/lib")
local Charm = require("../src")
local suite = require("@test/suite")
local atom = Charm.atom

View file

@ -1,4 +1,4 @@
local Charm = require("../src/lib")
local Charm = require("../src")
local suite = require("@test/suite")
type Atom<T> = Charm.Atom<T>

View file

@ -1,4 +1,4 @@
local Charm = require("../src/lib")
local Charm = require("../src")
local suite = require("@test/suite")
local atom = Charm.atom

View file

@ -5,6 +5,7 @@ local effect = Charm.effect
local useBinding = React.useBinding
local useEffect = React.useEffect
local useState = React.useState
local useMemo = React.useMemo
--- A hook that subscribes to changes in the given atom or selector. The
--- component is re-rendered whenever the state changes.
@ -39,7 +40,8 @@ end
--- @param dependencies An array of values that the subscription depends on.
--- @return A binding that stores the current state.
local function useAtomBinding<State>(selector: () -> State, dependencies: { any }?)
local binding, setBinding = useBinding(selector)
local initialState = useMemo(selector, {})
local binding, setBinding = useBinding(initialState)
useEffect(function()
return effect(function()

View file

@ -1,9 +0,0 @@
local lib = require(script.lib)
export type Atom<T = any> = lib.Atom<T>
export type Getter<T = any> = lib.Getter<T>
export type Selector<T = any> = lib.Selector<T>
export type Setter<T = any> = lib.Setter<T>
export type Update<T = any> = lib.Update<T>
return lib

164
pnpm-lock.yaml generated Normal file
View file

@ -0,0 +1,164 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
devDependencies:
'@rbxts-js/react':
specifier: 17.1.20-ts.1
version: 17.1.20-ts.1
'@rbxts-js/react-roblox':
specifier: 17.1.20-ts.1
version: 17.1.20-ts.1
'@rbxts/vide':
specifier: ^0.5.7
version: 0.5.7
packages:
'@rbxts-js/boolean@1.2.3-ts.1':
resolution: {integrity: sha512-IlYFG9uatXQKXOLR1mdptVeEcxudwBCierO+Vu6VZRRaI+/+JDxUClm+QFZyce/kitwnDTmtNvhqVAUtFvCU0Q==}
'@rbxts-js/collections@1.2.3-ts.1':
resolution: {integrity: sha512-RYT73QyEdsV+DCQMtyzT2bZ1P12j2b+JSHVdb1x6xrDq/KdVEkk/QAzW+o22vPrLXbHa6/jA5bmVlgVcOOrIjA==}
'@rbxts-js/console@1.2.3-ts.1':
resolution: {integrity: sha512-qacyJE7bYf4n9448F7mn9e8Y5qljZb7QkSmsmnbQT2HA9Mecvg3gqc9RwCIdVkBV6o1AGVAHbatNQ3a39zPjaw==}
'@rbxts-js/es7-types@1.2.3-ts.1':
resolution: {integrity: sha512-Z7NitBQp6tyzsr5eKlSX54rmopKXpzGu33lYikjF37llrnGFBpnRcZgCJwHKYciloRmjUtnR/UohUNwbWyG9Zg==}
'@rbxts-js/instance-of@1.2.3-ts.1':
resolution: {integrity: sha512-3fKvDPvxHuEZALNBP2XdbXfzjEfbgsXAheCm1Jf5kC2r+HgszW+yqg4zY6TjW0pcsJM2JjH+fM52oomSNu3LLQ==}
'@rbxts-js/luau-polyfill@1.2.3-ts.1':
resolution: {integrity: sha512-2asgvWrOhf311rNgEM/fxMO3+xOVI63Cz1K1PobyZVtDdd87ZJ6RGiZSFl1EAeU77SZc8280toJDVs9YSwxWnA==}
'@rbxts-js/math@1.2.3-ts.1':
resolution: {integrity: sha512-mF7IMJJyxYE02cRNWJ1wsq4pPaAEXKX+CbGlmI0G3QBgWVHj+Oi02IR6pssyUyE6Y2BKvgvP3dcJuTO51OX25A==}
'@rbxts-js/number@1.2.3-ts.1':
resolution: {integrity: sha512-tPdt2s7fEBSxImVFBUvuSMtBKIvaZUCtlOjBl58Y0+GKB15VPXFIRW/5biVruXPnv9d4sDE3mh986ZxxN4UQ5w==}
'@rbxts-js/react-reconciler@17.1.20-ts.1':
resolution: {integrity: sha512-t4vY4nHeM+Scrs+9FbgNsuhK0QR6lg3SNWUhjbzvptNP+IA4+4F8TkHQghR2SSTxQDhegU02BTR7NBpk+AQcUw==}
'@rbxts-js/react-roblox@17.1.20-ts.1':
resolution: {integrity: sha512-Jv0mq+9txXptgsJ6MDWHgCTwsohaon9HhmllkUe29zkaMwE+di4cHqzF1tgV8VHYGG/LQoitXDddK03CA3L+2g==}
'@rbxts-js/react@17.1.20-ts.1':
resolution: {integrity: sha512-u/dNRTNj5AaVPuqJLza7FEJ24lyRfJ0CdjflbIS8JiUS1iXiO7yZeHQWwPk6V3oHuAOckv6tA4FN/Eju2rPMrQ==}
'@rbxts-js/roblox-lua-promise@3.5.0-ts.2':
resolution: {integrity: sha512-H8fxKVJkRnM60yTZ/riO4X43GZD/MViFm+ftCzzAALkAhE4vSaBDNv9E7IUjZZoWi21bG6vZ8mGIiYfavaljvw==}
'@rbxts-js/safe-flags@17.1.20-ts.1':
resolution: {integrity: sha512-k+16jmCP63LT8sNfhLoytUrp3UB+CGHH7s54BFUAHte+zCANK3wfAKXbpT36NqnUfRqgKDM8grO4lWp6awuacQ==}
'@rbxts-js/scheduler@17.1.20-ts.1':
resolution: {integrity: sha512-RoXs6bAW3LIB6HL/voMilR2hjcGAtutaVsr0yumu0hUYVFY2FwIkbOVepsdYWDrYhVqsk5zrj8CcVGgUxDldGg==}
'@rbxts-js/shared@17.1.20-ts.1':
resolution: {integrity: sha512-/3K1BnWV519+any6JMWniIDx1rtq20H6RVgJStSCj4XofrM63kzju0EzRQg1af4lnXCfZNZBusRW8IGQ14xuZQ==}
'@rbxts-js/string@1.2.3-ts.1':
resolution: {integrity: sha512-Je/WKgZbXF/sAHEsQPuns5n4rWzux327zjr0KRf9Gy62ieUzl2FRZZHjVYce3xdMtHif2JstIf/J3p513TUtRg==}
'@rbxts-js/symbol-luau@1.0.0-ts.1':
resolution: {integrity: sha512-TQS/ImDCK5KPGvbmyScH5EZS0ELSCDvZEFR3W+ItPlsLl+bDRSI/0uaKtJ7rbwXgdGwBDKM1QXFPjqe+KOphIA==}
'@rbxts-js/timers@1.2.3-ts.1':
resolution: {integrity: sha512-HKP4ymFX3QLWbR/2Gy4LXwvkhjC9OzbwZ5bNunxu+M8Ocbi1cjRduiZK/y5ogLr9cNIfSoxs6e1DQ3soc8/hwA==}
'@rbxts/vide@0.5.7':
resolution: {integrity: sha512-Q9R7ybzuHK1phtLicBHgAjQnlJ/dMsXDs2k296PIMLgLqK9aX/f1skOP7F1K/vo7IrSE0jCG3B3XTOtQL1Sb0Q==}
snapshots:
'@rbxts-js/boolean@1.2.3-ts.1':
dependencies:
'@rbxts-js/collections': 1.2.3-ts.1
'@rbxts-js/collections@1.2.3-ts.1':
dependencies:
'@rbxts-js/es7-types': 1.2.3-ts.1
'@rbxts-js/instance-of': 1.2.3-ts.1
'@rbxts-js/console@1.2.3-ts.1':
dependencies:
'@rbxts-js/collections': 1.2.3-ts.1
'@rbxts-js/es7-types@1.2.3-ts.1': {}
'@rbxts-js/instance-of@1.2.3-ts.1': {}
'@rbxts-js/luau-polyfill@1.2.3-ts.1':
dependencies:
'@rbxts-js/boolean': 1.2.3-ts.1
'@rbxts-js/collections': 1.2.3-ts.1
'@rbxts-js/console': 1.2.3-ts.1
'@rbxts-js/es7-types': 1.2.3-ts.1
'@rbxts-js/instance-of': 1.2.3-ts.1
'@rbxts-js/math': 1.2.3-ts.1
'@rbxts-js/number': 1.2.3-ts.1
'@rbxts-js/string': 1.2.3-ts.1
'@rbxts-js/symbol-luau': 1.0.0-ts.1
'@rbxts-js/timers': 1.2.3-ts.1
'@rbxts-js/math@1.2.3-ts.1': {}
'@rbxts-js/number@1.2.3-ts.1': {}
'@rbxts-js/react-reconciler@17.1.20-ts.1':
dependencies:
'@rbxts-js/luau-polyfill': 1.2.3-ts.1
'@rbxts-js/react': 17.1.20-ts.1
'@rbxts-js/roblox-lua-promise': 3.5.0-ts.2
'@rbxts-js/safe-flags': 17.1.20-ts.1
'@rbxts-js/scheduler': 17.1.20-ts.1
'@rbxts-js/shared': 17.1.20-ts.1
'@rbxts-js/react-roblox@17.1.20-ts.1':
dependencies:
'@rbxts-js/luau-polyfill': 1.2.3-ts.1
'@rbxts-js/react': 17.1.20-ts.1
'@rbxts-js/react-reconciler': 17.1.20-ts.1
'@rbxts-js/scheduler': 17.1.20-ts.1
'@rbxts-js/shared': 17.1.20-ts.1
'@rbxts-js/react@17.1.20-ts.1':
dependencies:
'@rbxts-js/luau-polyfill': 1.2.3-ts.1
'@rbxts-js/shared': 17.1.20-ts.1
'@rbxts-js/roblox-lua-promise@3.5.0-ts.2': {}
'@rbxts-js/safe-flags@17.1.20-ts.1': {}
'@rbxts-js/scheduler@17.1.20-ts.1':
dependencies:
'@rbxts-js/luau-polyfill': 1.2.3-ts.1
'@rbxts-js/safe-flags': 17.1.20-ts.1
'@rbxts-js/shared': 17.1.20-ts.1
'@rbxts-js/shared@17.1.20-ts.1':
dependencies:
'@rbxts-js/luau-polyfill': 1.2.3-ts.1
'@rbxts-js/safe-flags': 17.1.20-ts.1
'@rbxts-js/string@1.2.3-ts.1':
dependencies:
'@rbxts-js/es7-types': 1.2.3-ts.1
'@rbxts-js/number': 1.2.3-ts.1
'@rbxts-js/symbol-luau@1.0.0-ts.1': {}
'@rbxts-js/timers@1.2.3-ts.1':
dependencies:
'@rbxts-js/collections': 1.2.3-ts.1
'@rbxts/vide@0.5.7': {}

View file

@ -8,5 +8,5 @@ wally = "UpliftGames/wally@0.3.2"
rojo = "rojo-rbx/rojo@7.5.1"
stylua = "johnnymorganz/stylua@2.1.0"
selene = "Kampfkarren/selene@0.28.0"
luau-lsp = "johnnymorganz/luau-lsp@1.44.1"
lute = "luau-lang/lute@0.1.0-nightly.20250511"
luau-lsp = "johnnymorganz/luau-lsp@1.47.0"
lute = "luau-lang/lute@0.1.0-nightly.20250518"

View file

@ -4,9 +4,6 @@ if not table.isfrozen(_G) then
_G.__DEV__ = true
end
require("@pkgs/charm/tests/spec")
require("@packages/charm/tests/spec")
suite.finish({
colors = true,
verbose = false,
})
suite.finish()

1
test/suite Submodule

@ -0,0 +1 @@
Subproject commit 2692eb055839cd56d0075ca72482658a5bdaddb9

View file

@ -1,438 +0,0 @@
type Config = {
colors: boolean?,
verbose: boolean?,
}
type Description = {
status: number,
name: string,
only: boolean,
skip: boolean,
parent: Description?,
children: { Description | Test },
passes: number,
fails: number,
skips: number,
runtime: number,
}
type Test = {
status: number,
name: string,
only: boolean,
skip: boolean,
parent: Description?,
children: nil,
run: () -> (),
result: unknown?,
line: number?,
runtime: number,
}
local options = {
colors = true,
verbose = false,
}
local color = {
white = function(text: string)
return if options.colors then `\27[37;1m{text}\27[0m` else text
end,
gray = function(text: string)
return if options.colors then `\27[90;1m{text}\27[0m` else text
end,
green = function(text: string)
return if options.colors then `\27[32;1m{text}\27[0m` else `\u{1F7E2} {text}`
end,
red = function(text: string)
return if options.colors then `\27[31;1m{text}\27[0m` else `\u{1F534} {text}`
end,
blue = function(text: string)
return if options.colors then `\27[34;1m{text}\27[0m` else `\u{1F535} {text}`
end,
}
local PENDING = 0
local PASS = 1
local FAIL = 2
local SKIP = 3
local ERROR = 4
local tests: { Test } = {}
local descriptions: { Description } = {}
local root: Description = {
status = PENDING,
name = "root",
only = false,
skip = false,
children = {},
passes = 0,
fails = 0,
skips = 0,
runtime = 0,
}
local parent: Description = root
local function describe(name: string, run: () -> ()): Description
local this: Description = {
status = PENDING,
name = name,
only = false,
skip = false,
parent = parent,
children = {},
passes = 0,
fails = 0,
skips = 0,
runtime = 0,
}
local prevDescription = parent
parent = this
run()
parent = prevDescription
table.insert(parent.children, this)
table.insert(descriptions, this)
return this
end
local function test(name: string, run: () -> ()): Test
local this: Test = {
status = PENDING,
name = name,
only = false,
skip = false,
parent = parent,
run = run,
runtime = 0,
}
table.insert(parent.children, this)
table.insert(tests, this)
return this
end
local function skip()
parent.skip = true
end
local function only()
parent.only = true
root.only = true
end
local function testSkip(name: string, run: () -> ()): Test
local this = test(name, run)
this.skip = true
return this
end
local function testOnly(name: string, run: () -> ()): Test
local this = test(name, run)
this.only = true
root.only = true
return this
end
local function describeSkip(name: string, run: () -> ()): Description
local this = describe(name, run)
this.skip = true
return this
end
local function describeOnly(name: string, run: () -> ()): Description
local this = describe(name, run)
this.only = true
root.only = true
return this
end
local function isOnly(test: Test): boolean
if not root.only or test.only then
return true
end
local description = test.parent
while description and description ~= root do
if description.only then
return true
elseif description.skip then
return false
end
description = description.parent
end
return false
end
local function isSkip(test: Test): boolean
if test.only then
return false
elseif test.skip then
return true
end
local description = test.parent
while description do
if description.only and description ~= root then
return false
elseif description.skip then
return true
end
description = description.parent
end
return false
end
local function runTests()
for _, test in tests do
if isSkip(test) or not isOnly(test) then
test.status = SKIP
continue
end
local start = os.clock()
local success = xpcall(test.run, function(result)
test.status = FAIL
test.result = result
test.line = debug.info(3, "l")
end)
test.runtime = os.clock() - start
if success then
test.status = PASS
end
end
end
local function updateDescription(description: Description)
if not description.children[1] then
description.status = PASS
return
end
description.status = SKIP
for _, child in description.children do
if child.children then
updateDescription(child)
description.passes += child.passes
description.fails += child.fails
elseif child.status == PASS then
description.passes += 1
elseif child.status == FAIL then
description.fails += 1
end
-- Only count skips in direct children
if child.status == SKIP then
description.skips += 1
end
description.runtime += child.runtime
if child.status == FAIL then
description.status = FAIL
elseif description.status == SKIP and child.status == PASS then
description.status = PASS
end
end
end
local function getIndent(node: Description | Test): string
local depth = 0
local description = node.parent
while description and description ~= root do
depth += 1
description = description.parent
end
return if depth > 0 then string.rep(" ", depth - 1) .. color.gray("· ") else ""
end
local function getPath(node: Description | Test): string
local path = { "" }
local description = node.parent
while description and description ~= root do
table.insert(path, 1, description.name)
description = description.parent
end
return table.concat(path, " > ")
end
local function greenOrRed(text: string, good: boolean): string
return if good then color.green(text) else color.red(text)
end
local function colorStatus(status: number): string
local wall = color.gray("│")
if status == PASS then
return color.green("PASS") .. wall
elseif status == FAIL then
return color.red("FAIL") .. wall
elseif status == SKIP then
return color.blue("SKIP") .. wall
else
return color.red("ERROR") .. wall
end
end
local function report()
local output = {}
local function reportDescription(description: Description)
local name = color.white(description.name)
local text = `{colorStatus(description.status)} {getIndent(description)}{name}`
if description.fails > 0 then
text ..= " " .. color.red(`({description.fails})`)
end
if description.skips > 0 then
text ..= " " .. color.blue(`({description.skips} skipped)`)
elseif description.fails == 0 then
text ..= " " .. color.gray(string.format("%.2fms", description.runtime * 1000))
end
table.insert(output, text)
end
local function reportTest(test: Test, reportError: boolean?)
if test.status ~= FAIL and not options.verbose then
return
end
local line = color.red(`{test.line}:`)
if reportError then
local name = color.white(test.name)
local path = color.gray(getPath(test))
table.insert(output, `{colorStatus(ERROR)} {path}{line}{name}`)
table.insert(output, `{test.result}`)
else
local name = color.gray(test.name)
local indent = getIndent(test)
if test.status == FAIL then
table.insert(output, `{colorStatus(FAIL)} {indent}{line}{name}`)
else
table.insert(output, `{colorStatus(test.status)} {indent}{name}`)
end
end
end
local function reportNode(node: Description | Test)
if not node.children then
return reportTest(node :: Test)
end
reportDescription(node)
for _, child in node.children do
reportNode(child)
end
end
local function reportSummary()
local describePasses = 0
local describeFails = 0
for _, description in descriptions do
if description.status == PASS then
describePasses += 1
elseif description.status == FAIL then
describeFails += 1
end
end
local describes =
`{greenOrRed(`{describePasses} passed`, describeFails == 0)} {color.gray(`({#descriptions})`)}`
local tests = `{greenOrRed(`{root.passes} passed`, root.fails == 0)} {color.gray(`({#tests})`)}`
local duration = `{color.blue(`{string.format("%.2fms", root.runtime * 1000)}`)}`
table.insert(output, "")
table.insert(output, `Describe {describes}`)
table.insert(output, ` Tests {tests}`)
table.insert(output, `Duration {duration}`)
table.insert(output, "")
end
local function reportErrors()
if root.fails == 0 then
return
end
for _, test in tests do
if test.status == FAIL then
reportTest(test, true)
table.insert(output, "")
end
end
end
table.insert(output, "")
table.insert(output, color.blue("Test Results"))
table.insert(output, "")
for _, child in root.children do
reportNode(child)
end
reportSummary()
reportErrors()
print(table.concat(output, "\n"))
if root.fails > 0 then
error(color.red(`{root.fails} test(s) failed`))
end
end
local function finish(config: Config?)
if config then
options.colors = if config.colors ~= nil then config.colors else options.colors
options.verbose = if config.verbose ~= nil then config.verbose else options.verbose
end
runTests()
updateDescription(root)
report()
end
local testCtor = setmetatable({
skip = testSkip,
only = testOnly,
}, {
__call = function(_, ...)
return test(...)
end,
})
local describeCtor = setmetatable({
skip = describeSkip,
only = describeOnly,
}, {
__call = function(_, ...)
return describe(...)
end,
})
return {
test = testCtor :: ((name: string, callback: () -> ()) -> ()) & {
skip: (name: string, callback: () -> ()) -> (),
only: (name: string, callback: () -> ()) -> (),
},
describe = describeCtor :: ((name: string, callback: () -> ()) -> ()) & {
skip: (name: string, callback: () -> ()) -> (),
only: (name: string, callback: () -> ()) -> (),
},
skip = skip,
only = only,
finish = finish,
}

View file

@ -1,98 +0,0 @@
# This file is automatically @generated by Wally.
# It is not intended for manual editing.
registry = "test"
[[package]]
name = "centau/vide"
version = "0.3.1"
dependencies = []
[[package]]
name = "jsdotlua/boolean"
version = "1.2.7"
dependencies = [["number", "jsdotlua/number@1.2.7"]]
[[package]]
name = "jsdotlua/collections"
version = "1.2.7"
dependencies = [["es7-types", "jsdotlua/es7-types@1.2.7"], ["instance-of", "jsdotlua/instance-of@1.2.7"]]
[[package]]
name = "jsdotlua/console"
version = "1.2.7"
dependencies = [["collections", "jsdotlua/collections@1.2.7"]]
[[package]]
name = "jsdotlua/es7-types"
version = "1.2.7"
dependencies = []
[[package]]
name = "jsdotlua/instance-of"
version = "1.2.7"
dependencies = []
[[package]]
name = "jsdotlua/luau-polyfill"
version = "1.2.7"
dependencies = [["boolean", "jsdotlua/boolean@1.2.7"], ["collections", "jsdotlua/collections@1.2.7"], ["console", "jsdotlua/console@1.2.7"], ["es7-types", "jsdotlua/es7-types@1.2.7"], ["instance-of", "jsdotlua/instance-of@1.2.7"], ["math", "jsdotlua/math@1.2.7"], ["number", "jsdotlua/number@1.2.7"], ["string", "jsdotlua/string@1.2.7"], ["symbol-luau", "jsdotlua/symbol-luau@1.0.1"], ["timers", "jsdotlua/timers@1.2.7"]]
[[package]]
name = "jsdotlua/math"
version = "1.2.7"
dependencies = []
[[package]]
name = "jsdotlua/number"
version = "1.2.7"
dependencies = []
[[package]]
name = "jsdotlua/promise"
version = "3.5.2"
dependencies = []
[[package]]
name = "jsdotlua/react"
version = "17.2.1"
dependencies = [["luau-polyfill", "jsdotlua/luau-polyfill@1.2.7"], ["shared", "jsdotlua/shared@17.2.1"]]
[[package]]
name = "jsdotlua/react-reconciler"
version = "17.2.1"
dependencies = [["luau-polyfill", "jsdotlua/luau-polyfill@1.2.7"], ["promise", "jsdotlua/promise@3.5.2"], ["react", "jsdotlua/react@17.2.1"], ["scheduler", "jsdotlua/scheduler@17.2.1"], ["shared", "jsdotlua/shared@17.2.1"]]
[[package]]
name = "jsdotlua/react-roblox"
version = "17.2.1"
dependencies = [["luau-polyfill", "jsdotlua/luau-polyfill@1.2.7"], ["react", "jsdotlua/react@17.2.1"], ["react-reconciler", "jsdotlua/react-reconciler@17.2.1"], ["scheduler", "jsdotlua/scheduler@17.2.1"], ["shared", "jsdotlua/shared@17.2.1"]]
[[package]]
name = "jsdotlua/scheduler"
version = "17.2.1"
dependencies = [["luau-polyfill", "jsdotlua/luau-polyfill@1.2.7"], ["shared", "jsdotlua/shared@17.2.1"]]
[[package]]
name = "jsdotlua/shared"
version = "17.2.1"
dependencies = [["luau-polyfill", "jsdotlua/luau-polyfill@1.2.7"]]
[[package]]
name = "jsdotlua/string"
version = "1.2.7"
dependencies = [["es7-types", "jsdotlua/es7-types@1.2.7"], ["number", "jsdotlua/number@1.2.7"]]
[[package]]
name = "jsdotlua/symbol-luau"
version = "1.0.1"
dependencies = []
[[package]]
name = "jsdotlua/timers"
version = "1.2.7"
dependencies = [["collections", "jsdotlua/collections@1.2.7"]]
[[package]]
name = "richerd/charm"
version = "0.1.0"
dependencies = [["React", "jsdotlua/react@17.2.1"], ["ReactRoblox", "jsdotlua/react-roblox@17.2.1"], ["Vide", "centau/vide@0.3.1"]]

View file

@ -1,10 +0,0 @@
[package]
name = "richerd/charm"
version = "0.1.0"
registry = "https://github.com/UpliftGames/wally-index"
realm = "shared"
[dev-dependencies]
React = "jsdotlua/react@17"
ReactRoblox = "jsdotlua/react-roblox@17"
Vide = "centau/vide@0.3"