neurodynamic

neurodynamic

I have a page in my Phoenix app with some LiveView code. When you click a button, it shows the Stripe credit card modal form via a Hook. It looks roughly like this:

Hooks.StripeFormButton = {
  mounted() {    
    this.el.addEventListener("click", () => {
      showStripeForm({
        onSuccess: (token) => {
          this.pushEvent("save-card", {token: token})
        }
      })
    })
  }
}

So a user clicks the button, fills out the Stripe form, and when they submit it, the "save-card" event gets sent to the back-end. That will save their credit card info and then render some info to show that the save was successful.

My problem is, since the click and the form submit are done through hooks instead of phx-click and phx-submit attributes, I can’t figure out a way to test them. I want to be able to write a test that says “after the "save-card" event gets triggered, a confirmation message shows on the page”. But I can’t find a way to trigger the "save-card" event in a LiveView test without using something like render_click or render_submit which won’t work since I’m not using phx-click or phx-submit for the Stripe form. Is there a push_event testing function somewhere that I’m missing in the documentation? Or is there another way to do this?

Showing Posts 1 to 10

outlog

outlog

think you’ll need to test using something like wallaby eg headless chrome/firefox.. since this requires a js runtime..

you can see https://www.tddphoenix.com for getting started - excellent resource..

could be wrong though, but don’t see how elixir side should/can know what goes on in js hooks..

neurodynamic

neurodynamic OP

Something like that is definitely an option, but I’m hoping there’s a way to just trigger the event within a LiveView test in elixir. There’s no way to invoke the Stripe form or fill it out without a tool like wallaby, but it seems like there ought to be a way to simulate the this.pushEvent call that would normally happen on the form submit.

The closest I’ve been able to get so far is setting up a handle_info function that works the same way handle_event does and testing that, because with handle_info, I can trigger it in the test like this

send(view.pid, {:test_save_card, "some stripe token"})

and if my setup looks like this

  def handle_event("save-card", %{"token" => stripe_token}, socket) do
    save_card(stripe_token, socket)
  end

  def handle_info({:test_save_card, stripe_token}, socket) do
    save_card(stripe_token, socket)
  end

then when handle_info tests pass, it should be a good bet that handle_event tests, if they were possible to write, would pass the same way. It’s hacky, but it basically works. Unfortunately, as far as I can tell, there’s no analog to send(view.pid, {:test_save_card, "some stripe token"}) that works to trigger handle_event.

amnu3387

amnu3387

If you have the socket in the test (I haven’t written any tests with liveview, but I imagine you have?) you can just call YourLiveView.Module.handle_event("save-card", %{"token" => "your_token"}, the_socket) and assert on the result of save card and any side effects?

This doesn’t test the client interface tough, just that if an event "save-card" with those params are sent through the live view it works correctly.

neurodynamic

neurodynamic OP

Yes, I think this might work, but so far I haven’t been able to figure out how to get access to the socket in tests, either :confused:

amnu3387

amnu3387

Yeah probably it’s possible to build the socket manually but I didn’t see any helpers for that while giving it a quick glance. I thought it would allow as it does with channels (the phx channelcase) you have some helpers to build it though.

PJUllrich

PJUllrich

Author of Building Table Views with Phoenix LiveView

Just FYI: There’s the render_hook/3 option now, which simulates sending an event through this.pushEvent("foo", "bar") in your JavaScript. It will then trigger the handle_event("foo", "bar", socket)-callback in your LiveView.

So, in your use case, you could write a test like:

render_hook(view, "save-card", %{"token" => stripe_token})
neurodynamic

neurodynamic OP

That works perfectly; thank you!

dustin

dustin

I’d still like to know how to access the socket. I have a handle_event that gets called from the browser when a user releases the mouse button after drawing a box on an image.

My handle_event saves the latest coordinates in the assigns and then fires back all the boxes that the user has drawn to the browser to re-render them in JavaScript. I’d love to be able to assert that the assigns has the right data after processing what came back from the browser on mouseup.

sulphur

sulphur

Someone know how to test pushEventTo when targeting component ? render_hook/3 requires that component has the phx-hook on the target component however in my case i have the div with phx-hook outside and it uses the pushEventTo("from", ...) to update crop zone in real time. It is a multi file upload where user before uploading can crop all images in order to select required zone with correct aspect. So to test it i need to execute the handle_event on my FormComponent.
And when i do

      view
      |> element("form")
      |> render_hook("update-crop", %{crop_map: ...})

I have error that element selected by "form" does not have phx-hook attribute. which is true of course because hook is outside.

I have something like that :

  <%= for entry <- @uploads.image_file.entries do %>
      <div phx-hook="CropperComponent" phx-update="ignore" id={"Cropper-#{entry.uuid}"}>
        <%= live_img_preview entry %>
        ...
      </div>
    </div>
  <% end %>

  <.form let={f} for={@changeset} phx-target={@myself} phx-change="validate" phx-submit="save">
     ....
     <%= submit "Save" %>
  </.form>
unyraw

unyraw

Bit of a late answer, but could potentially help someone coming across this post :

You need to target the element with phx-hook attached to it. In your case it would be the div(s) you perform the iteration on.

Also, if your code resides in a Live Component and you don’t want the pushEventTo to be sent to the parent, you need to add a phx-target={@myself} on the targetted element.

— All posts loaded —

Where Next? Top

Trending in Questions Top

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
Onor.io
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
Trolleger
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
matt-savvy
Anyone here using Honeybadger? My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of Bandit.HTTPError...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews