phoenix_ecto icon indicating copy to clipboard operation
phoenix_ecto copied to clipboard

Enable caller tracking for async LV tests using the sandbox

Open LostKobrakai opened this issue 5 months ago • 10 comments

LiveViews async apis use Tasks under the hood, which already implement caller tracking, but as documented for Phoenix.Ecto.SQL.Sandbox and async LV tests :"$callers" is not set on the LV itself, so allowance can't be automatically inherited.

I'm not sure if Phoenix.Ecto.SQL.Sandbox should get updated or just its docs.

Context: https://elixirforum.com/t/running-a-liveview-test-with-async-true/68765/24

LostKobrakai avatar Sep 07 '25 06:09 LostKobrakai

This is weird. $callers is definitely set for LV during regular tests. It won't be set for acceptance tests, but that's because you bypass the testing infrastructure.

In any case, $callers is automatically set for tasks and I would expect that, if something allowed is in callers, then that should be enough. It may be a bug in DBConnection.

josevalim avatar Sep 07 '25 06:09 josevalim

Ok, I can confirm that DBConnection should be happy if any of the allowances is in callers: https://github.com/elixir-ecto/db_connection/commit/ebc05b17dd2763c18aa5f776e7fe1acdd2cdf3ed

So if you allow the LV and the task points to the LV in its callers, that's enough. LV does not need to have its $callers set. So there is something else going on here. A reproducer would be very helpful!

josevalim avatar Sep 07 '25 07:09 josevalim

They mention in the forum that they’re not using manual mode, so it’s related to https://github.com/phoenixframework/phoenix_ecto/issues/157

SteffenDE avatar Sep 07 '25 07:09 SteffenDE

You are not supposed to use auto mode indeed.

  • :manual mode - requires explicit checkout and allowances through the sandbox
  • :auto mode - each process gets a new connection
  • :shared mode - all processes use the same connection

josevalim avatar Sep 07 '25 07:09 josevalim

I’ll send a code snippet later for something I did in the past to make assign_async / start_async behave automatically when I also used auto mode.

SteffenDE avatar Sep 07 '25 07:09 SteffenDE

I wouldn’t expect auto mode to work at all, so if the assumption is that auto mode is used, then it is expected for it to fail. You should use either manual or shared mode with the sandbox. :)

josevalim avatar Sep 07 '25 07:09 josevalim

Yeah, given the usage of the phoenix sandbox module I was expecting acceptance tests. There is an example of how to do acceptance tests with LV in the docs, but I‘m not sure how to best add caller tracking to that. In the example on the docs one wouldn‘t even get access to the owner pid.

LostKobrakai avatar Sep 07 '25 09:09 LostKobrakai

https://gist.github.com/SteffenDE/18e3baa5a70e03fb9e2650fb2fdcf13b

That's something I did in the past for auto mode. I'm not saying it's pretty, but it worked. Using as use MyApp.LiveView instead of use Phoenix.LiveView. Similar thing can be done for LiveComponent as well.

In this case, we had a separate :e2e Mix environment for those tests.

Yeah, given the usage of the phoenix sandbox module I was expecting acceptance tests.

I need to check if something changed though, because we're also using the sandbox for Playwright tests in a Dashbit project and the async functions work just fine. And as far as I can tell, it's also running the pool in auto mode.

SteffenDE avatar Sep 07 '25 10:09 SteffenDE

I don't think you need to traverse the AST in the example above. You can do import Phoenix.LiveView.Whatever, except: [start_async: ..., assign_async: ...] and import the ones from the module afterwards. It requires you to use MyModule after use Phoenix.LiveView, which can be done in the web.ex file.

josevalim avatar Sep 07 '25 10:09 josevalim

Iirc the problems was that there were warnings and we have --warnings-as-errors, but I don't think we tried two separate use calls :D

SteffenDE avatar Sep 07 '25 10:09 SteffenDE