diff --git a/.busted b/.busted new file mode 100644 index 0000000..d2d1541 --- /dev/null +++ b/.busted @@ -0,0 +1,8 @@ +-- Adds the sources to Lua's path so that busted can find all the modules +require "set_paths" + +return { + default = { + loaders = { "teal" }, + }, +} diff --git a/.editorconfig b/.editorconfig index bcfe9f9..dc552b6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,6 +14,9 @@ indent_size = 3 [*.{tl,d.tl}] indent_size = 3 +[.busted] +indent_size = 3 + [justfile] indent_size = 2 diff --git a/.vscode/settings.json b/.vscode/settings.json index beb9a87..e6d1c39 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -29,6 +29,7 @@ "luasec", "luasocket", "mkdir", + "rockspec", "setopt", "Stylua", "tablex", @@ -39,6 +40,7 @@ ], "files.associations": { ".luacheckrc": "lua", - "*.rockspec": "lua" + "*.rockspec": "lua", + ".busted": "lua" } } diff --git a/.woodpecker/build.yml b/.woodpecker/build.yml index de2ee51..0d0a370 100644 --- a/.woodpecker/build.yml +++ b/.woodpecker/build.yml @@ -22,3 +22,6 @@ pipeline: # - tree generated branches: master + +depends_on: + - docker-build diff --git a/.woodpecker/docker-build.yml b/.woodpecker/docker-build.yml index 473d7dd..2879df1 100644 --- a/.woodpecker/docker-build.yml +++ b/.woodpecker/docker-build.yml @@ -7,6 +7,7 @@ matrix: - Dockerfile.cyan - Dockerfile.luacheck_just - Dockerfile.stylua_just + - Dockerfile.busted-tl_just pipeline: dryrun: diff --git a/.woodpecker/docker/Dockerfile.busted-tl_just b/.woodpecker/docker/Dockerfile.busted-tl_just new file mode 100644 index 0000000..8501499 --- /dev/null +++ b/.woodpecker/docker/Dockerfile.busted-tl_just @@ -0,0 +1,9 @@ +FROM akorn/luarocks:lua5.4-alpine +ARG CYAN_VERSION=0.3.0 +RUN \ + apk add \ + git \ + gcc libc-dev \ + just \ + && luarocks install --server=https://luarocks.org/dev busted-tl + diff --git a/.woodpecker/lint.yml b/.woodpecker/lint.yml index bab07c2..5d97420 100644 --- a/.woodpecker/lint.yml +++ b/.woodpecker/lint.yml @@ -43,3 +43,6 @@ pipeline: path: *when_path_teal branches: master + +depends_on: + - docker-build diff --git a/.woodpecker/test.yml b/.woodpecker/test.yml new file mode 100644 index 0000000..4fa84e1 --- /dev/null +++ b/.woodpecker/test.yml @@ -0,0 +1,17 @@ +variables: + - &busted gitea.aireone.xyz/aire-one/awesomewm.d.tl/busted-tl_just:latest + +pipeline: + prepare: + image: *busted + commands: + - just install + test: + image: *busted + commands: + - just test + +branches: master + +depends_on: + - docker-build diff --git a/README.MD b/README.MD index 89a820a..ee21b00 100644 --- a/README.MD +++ b/README.MD @@ -3,9 +3,10 @@ A project to generate Teal types definitions for the Awesome WM based on the API documentation. [![status-badge](https://woodpecker.aireone.xyz/api/badges/Aire-One/awesomewm.d.tl/status.svg)](https://woodpecker.aireone.xyz/Aire-One/awesomewm.d.tl) + # Dependencies -Project dependencies : +## Project dependencies - Lua5.4 - Luarocks @@ -13,10 +14,11 @@ Project dependencies : Note that additional dependencies are installed as rocks with Luarocks. -Development dependencies: +## Development dependencies - Luacheck - Stylua +- Busted-tl (https://gitea.aireone.xyz/Aire-One/busted-tl) # Run the project diff --git a/justfile b/justfile index 2332d58..0cd6a5d 100644 --- a/justfile +++ b/justfile @@ -46,6 +46,9 @@ validate: --global-env-def "global_env" \ `find . -type f -iname '*.d.tl' | xargs` +test: + busted + # TODO : how to run a debugger on Teal code? debug: {{ lua }} debug.lua build/awesomewm.d.tl/init.lua diff --git a/spec/example_spec.tl b/spec/example_spec.tl new file mode 100644 index 0000000..7448c7d --- /dev/null +++ b/spec/example_spec.tl @@ -0,0 +1,30 @@ +local assert = require("luassert") + +describe("Busted unit testing framework", function() + describe("should be awesome", function() + it("should be easy to use", function() + assert.truthy "Yup." + end) + + it("should have lots of features", function() + -- deep check comparisons! + assert.same({ table = "great" }, { table = "great" }) + + -- or check by reference! + assert.not_equal({ table = "great" }, { table = "great" }) + + assert.truthy "this is a string" -- truthy: not false or nil + + assert.is_true(1 == 1) + + assert.falsy(nil) + assert.has_error(function() + error "Wat" + end, "Wat") + end) + + it("should provide some shortcuts to common functions", function() + assert.is_unique { { thing = 1 }, { thing = 2 }, { thing = 3 } } + end) + end) +end) diff --git a/spec/example_with_my_code_spec.tl b/spec/example_with_my_code_spec.tl new file mode 100644 index 0000000..a510409 --- /dev/null +++ b/spec/example_with_my_code_spec.tl @@ -0,0 +1,10 @@ +local assert = require("luassert") +local utils = require("utils") + +describe("test", function() + it("has_item", function() + local t = {1, 2, 3} + assert.equal(utils.has_item(t, 1), 1) + assert.is_nil(utils.has_item(t, 4)) + end) +end) diff --git a/spec/tlconfig.lua b/spec/tlconfig.lua new file mode 100644 index 0000000..33aee75 --- /dev/null +++ b/spec/tlconfig.lua @@ -0,0 +1,7 @@ +return { + include_dir = { + "../src/awesomewm.d.tl", + "../types", + }, + global_env_def = "busted", +} diff --git a/src/awesomewm.d.tl/property.tl b/src/awesomewm.d.tl/property.tl index 2d7c01d..8cbd797 100644 --- a/src/awesomewm.d.tl/property.tl +++ b/src/awesomewm.d.tl/property.tl @@ -19,7 +19,8 @@ end local property: Property = { -- base_url = "https://awesomewm.org/apidoc", - base_url = "file:///usr/share/doc/awesome/doc", + -- base_url = "file:///usr/share/doc/awesome/doc", + base_url = "file:///home/aireone/documents/prog/awesome/build/doc", index_uri = "/index.html", out_directory = "generated", capi_modules = { diff --git a/types/busted.d.tl b/types/busted.d.tl new file mode 100644 index 0000000..54dc9a4 --- /dev/null +++ b/types/busted.d.tl @@ -0,0 +1,14 @@ + +global describe: function(string, function()) +global it: function(string, function()) +global before_each: function(function()) +global after_each: function(function()) +global setup: function(function()) +global teardown: function(function()) +global async: function() +global done: function() +global insulate: function(string, function()) +global expose: function(string, function()) +global randomize: function() +global finally: function(function()) +global pending: function(string) diff --git a/types/luassert.d.tl b/types/luassert.d.tl new file mode 100644 index 0000000..759b8c4 --- /dev/null +++ b/types/luassert.d.tl @@ -0,0 +1,2 @@ + +return require("luassert.assert") diff --git a/types/luassert/assert.d.tl b/types/luassert/assert.d.tl new file mode 100644 index 0000000..3854960 --- /dev/null +++ b/types/luassert/assert.d.tl @@ -0,0 +1,204 @@ + +local record ArrayAssert + has_holes:function(integer) + has_no_holes:function() +end + +local record SpyAssert + was_called:function(integer) + was_not_called:function(integer) + + was_called_with:function(...:any) + was_not_called_with:function(...:any) + + was_returned_with:function(...:any) + was_not_returned_with:function(...:any) + + was_called_at_least:function(integer) + was_called_at_most:function(integer) + was_called_more_than:function(integer) + was_called_less_than:function(integer) + + was_not_called_at_least:function(integer) + was_not_called_at_most:function(integer) + was_not_called_more_than:function(integer) + was_not_called_less_than:function(integer) + + called:function(integer) + not_called:function() + + called_with:function(...:any) + not_called_with:function(...:any) + + returned_with:function(...:any) + not_returned_with:function(...:any) + + called_at_least:function(integer) + called_at_most:function(integer) + called_more_than:function(integer) + called_less_than:function(integer) +end + +-- We use asserts instead of assert here to avoid tl warning +local record asserts + -- True / false + is_not_true:function(any, string):any, string + is_true:function(any, string):any, string + + is_not_false:function(any, string):any, string + is_false:function(any, string):any, string + + is_not_truthy:function(any, string):any, string + is_truthy:function(any, string):any, string + + truthy:function(any, string):any, string + not_truthy:function(any, string):any, string + + is_not_falsy:function(any, string):any, string + is_falsy:function(any, string):any, string + + falsy:function(any, string):any, string + not_falsy:function(any, string):any, string + + -- Same-ness + same:function(any, any, string):any, any, string + + is_same:function(any, any, string):any, any, string + is_not_same:function(any, any, string):any, any, string + + are_same:function(any, any, string):any, any, string + are_not_same:function(any, any, string):any, any, string + + -- Equality + are_not_equal:function(any, any, string):any, any, string + are_not_equals:function(any, any, string):any, any, string + + is_not_equal:function(any, any, string):any, any, string + is_not_equals:function(any, any, string):any, any, string + + equal:function(any, any, string):any, any, string + equals:function(any, any, string):any, any, string + + not_equals:function(any, any, string):any, any, string + not_equal:function(any, any, string):any, any, string + + equals_not:function(any, any, string):any, any, string + equal_not:function(any, any, string):any, any, string + + is_equal:function(any, any, string):any, any, string + is_equals:function(any, any, string):any, any, string + + are_equal:function(any, any, string):any, any, string + are_equals:function(any, any, string):any, any, string + + -- Nearness + is_near:function(number, number, number, string):number, number, number, string + is_not_near:function(number, number, number, string):number, number, number, string + + -- Uniqueness + is_unique:function({any}, string):{any}, string + is_not_unique:function({any}, string):{any}, string + + are_unique:function({any}, string):{any}, string + are_not_unique:function({any}, string):{any}, string + + -- Errors function + is_error:function(function(), any, string):{any} + error:function(function(), any, string):{any} + errors:function(function(), any, string):{any} + + no_errors:function(function(), any, string):{any} + + has_no_errors:function(function(), any, string):{any} + has_no_error:function(function(), any, string):{any} + + has_error:function(function(), any, string):{any} + has_errors:function(function(), any, string):{any} + + record Callable + metamethod __call: function(self: Callable) + end + + -- Errors Callable + is_error:function(Callable, any, string):{any} + error:function(Callable, any, string):{any} + errors:function(Callable, any, string):{any} + + no_errors:function(Callable, any, string):{any} + + has_no_errors:function(Callable, any, string):{any} + has_no_error:function(Callable, any, string):{any} + + has_error:function(Callable, any, string):{any} + has_errors:function(Callable, any, string):{any} + + -- Errors matches + does_error_match:function(function(), string, string) + matches_error:function(function(), string, string) + has_no_error_match:function(function(), string, string) + does_not_match_error:function(function(), string, string) + + error_matches:function(function(), string, string):{any} + no_error_matches:function(function(), string, string):{any} + + -- Errors matches callable + does_error_match:function(Callable, string, string) + matches_error:function(Callable, string, string) + has_no_error_match:function(Callable, string, string) + does_not_match_error:function(Callable, string, string) + + error_matches:function(Callable, string, string):{any} + no_error_matches:function(Callable, string, string):{any} + + -- matches + matches:function(string, string, string) + + has_match:function(string, string, string):{string} + has_no_match:function(string, string, string):{string} + + -- type checking + is_boolean:function(any, string):any, string + is_not_boolean:function(any, string):any, string + + is_number:function(any, string):any, string + is_not_number:function(any, string):any, string + + is_string:function(any, string):any, string + is_not_string:function(any, string):any, string + + is_table:function(any, string):any, string + is_not_table:function(any, string):any, string + + is_function:function(any, string):any, string + is_not_function:function(any, string):any, string + + is_userdata:function(any, string):any, string + is_not_userdata:function(any, string):any, string + + is_thread:function(any, string):any, string + is_not_thread:function(any, string):any, string + + is_nil:function(any, string):any, string + is_not_nil:function(any, string):any, string + + -- misc + set_parameter:function(self:asserts, string, integer) + + returned_arguments:function(...:any) + not_returned_arguments:function(...:any) + + has_holes:function({any}) + has_no_holes:function({any}) + + array:function({any}):ArrayAssert + + spy:function(any):SpyAssert + stub:function(any):SpyAssert + + get_level:function(self:asserts, any) + level:function(self:asserts, integer) + + has_property:function(any, string) +end + +return asserts diff --git a/types/luassert/match.d.tl b/types/luassert/match.d.tl new file mode 100644 index 0000000..88b141b --- /dev/null +++ b/types/luassert/match.d.tl @@ -0,0 +1,102 @@ + +local record Matcher + metamethod __call: function(self: Matcher, any) +end + +local record match + _:function(any) + + match:function(any):Matcher + + -- truthiness + is_true:function():Matcher + is_false:function():Matcher + + is_not_true:function():Matcher + is_not_false:function():Matcher + + is_truthy:function():Matcher + is_falsy:function():Matcher + + is_not_truthy:function():Matcher + is_not_falsy:function():Matcher + + not_false:function():Matcher + + truthy:function():Matcher + falsy:function():Matcher + + -- type matching + is_boolean:function(any):Matcher + is_function:function():Matcher + is_nil:function():Matcher + is_number:function():Matcher + is_string:function():Matcher + is_table:function(any):Matcher + is_thread:function():Matcher + is_ref:function(any):Matcher + is_userdata:function():Matcher + + boolean:function(any):Matcher + number:function():Matcher + string:function():Matcher + table:function(any):Matcher + thread:function():Matcher + userdata:function():Matcher + ref:function():Matcher + + not_boolean:function(any):Matcher + not_function:function():Matcher + not_nil:function():Matcher + not_number:function():Matcher + not_string:function():Matcher + not_table:function(any):Matcher + not_thread:function():Matcher + not_userdata:function():Matcher + not_ref:function():Matcher + + is_not_boolean:function(any):Matcher + is_not_function:function():Matcher + is_not_nil:function():Matcher + is_not_number:function():Matcher + is_not_string:function():Matcher + is_not_table:function(any):Matcher + is_not_thread:function():Matcher + is_not_userdata:function():Matcher + is_not_ref:function():Matcher + + -- equality + is_equals:function():Matcher + is_equal:function(any):Matcher + is_same:function(any):Matcher + + equals:function(any):Matcher + equal:function(any):Matcher + same:function(any):Matcher + + is_unique:function():Matcher + is_not_unique:function():Matcher + + -- group matching + is_all_of:function(...:any):Matcher + is_any_of:function(...:any):Matcher + is_none_of:function(...:any):Matcher + + all_of:function(...:any):Matcher + any_of:function(...:any):Matcher + none_of:function(...:any):Matcher + + not_all_of:function(...:any):Matcher + not_any_of:function(...:any):Matcher + not_none_of:function(...:any):Matcher + + -- misc + matches:function(string, number):Matcher + has_match:function(string, number):Matcher + + near:function(number, number):Matcher + is_near:function(number, number):Matcher + is_not_near:function(number, number):Matcher +end + +return match diff --git a/types/luassert/mock.d.tl b/types/luassert/mock.d.tl new file mode 100644 index 0000000..a7eb94c --- /dev/null +++ b/types/luassert/mock.d.tl @@ -0,0 +1,9 @@ + +local record mock + clear:function(any) + revert:function(any) + + new:function(T, boolean):T +end + +return mock diff --git a/types/luassert/spy.d.tl b/types/luassert/spy.d.tl new file mode 100644 index 0000000..17d5843 --- /dev/null +++ b/types/luassert/spy.d.tl @@ -0,0 +1,14 @@ + +local record spy + clear:function(self:spy):spy + revert:function(self:spy):spy + + on:function(any, string):spy + + -- To call spy methods, cast it back to spy with 'as' + new:function(T):T + + metamethod __call: function(self: spy, ...:any) +end + +return spy diff --git a/types/luassert/stub.d.tl b/types/luassert/stub.d.tl new file mode 100644 index 0000000..0039e75 --- /dev/null +++ b/types/luassert/stub.d.tl @@ -0,0 +1,29 @@ + +local record stub + record Defaults + returns:function(...:any) + invokes:function(function(...:any)) + end + + record OnCallWith + returns:function(...:any) + invokes:function(function(...:any)) + end + + clear:function(self:stub):stub + revert:function(self:stub):stub + + on_call_with:function(...:any):OnCallWith + + returns:function(...:any):stub + invokes:function(function(...:any)):stub + + -- table, key, return values + new:function(any, string, ...:any):stub + + by_default:Defaults + + metamethod __call: function(self: stub, ...:any) +end + +return stub