Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support testing async code with callbacks #12

Open
luttje opened this issue Dec 2, 2024 · 0 comments · May be fixed by #13
Open

Support testing async code with callbacks #12

luttje opened this issue Dec 2, 2024 · 0 comments · May be fixed by #13
Assignees
Labels
enhancement New feature or request

Comments

@luttje
Copy link
Owner

luttje commented Dec 2, 2024

Currently there is no way to test async code.

API

Jest allows testing asynchronous code using callbacks:

// JavaScript - Jest
test('the data is peanut butter', done => {
  function callback(error, data) {
    if (error) {
      done(error);
      return;
    }
    try {
      expect(data).toBe('peanut butter');
      done();
    } catch (error) {
      done(error);
    }
  }

  fetchData(callback);
});

That API would translate to Lua pretty well:

-- Lua - Jestronaut (concept usage for Lua 5.2+ / LuaJIT / Garry's Mod)
test("the data is peanut butter", function(done)
  local function callback(error, data)
    if error then
      done(error)
      return
    end
    local success, err = pcall(function()
      expect(data):toBe("peanut butter")
      done()
    end)
    if not success then
      done(err)
    end
  end

  fetchData(callback)
end)

We get debug.getinfo(fn, "u").nparams since Lua 5.2 and in LuaJIT (and thus Garry's Mod), which allows us to determine if the fn has any parameters, allowing for a very similar API:

-- Lua - Jestronaut (concept implementation)
function test(mode, fn)
    local function has_parameter(func)
        return debug.getinfo(func, "u").nparams == 1
    end

    if type(fn) == "function" then
        if has_parameter(fn) then
            print(mode .. ": fn expects a parameter.")
        else
            print(mode .. ": fn does not expect a parameter.")
        end
    else
        print("Second argument is not a valid function.")
    end
end

-- Examples
test("sync", function() end)         -- sync: fn does not expect a parameter.
test("async", function(done) end)    -- async: fn expects a parameter.

Sadly for Lua 5.1 I can't find a way to detect the parameter count in the testing fn, so I guess we could have this alternative syntax for Lua 5.1, which would make it trivial to detect if a test function is long async:

-- Lua - Jestronaut (concept usage for Lua 5.1)
test("the data is peanut butter", async(function(done)
  local function callback(error, data)
    if error then
      done(error)
      return
    end
    local success, err = pcall(function()
      expect(data):toBe("peanut butter")
      done()
    end)
    if not success then
      done(err)
    end
  end

  fetchData(callback)
end))

I think the biggest challenge will be scheduling the tests in such a way that that they can actually be long running, without locking up all other tests. I'm not very familiar with Lua coroutines, which I think we'll need + I suspect a ton of refactoring might be needed.

Minimal prototype 1: https://pastebin.com/redFZMKw

@luttje luttje added the enhancement New feature or request label Dec 2, 2024
@luttje luttje self-assigned this Dec 2, 2024
@luttje luttje linked a pull request Dec 3, 2024 that will close this issue
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant