I recently added turbo_streams to a feature and I was trying to test the live updating. It 100% works in the browser while manually testing. That said, when I attempt to test it in a system test a weird behavior seems to be happening. Here’s the test
visit handwritten_design_path(design)
expect(page.find('#front_preview')['src']).to match(/loading/)
expect(page.find('#back_preview')['src']).to match(/loading/)
front_url = 'https://via.placeholder.com/150?text=front'
back_url = 'https://via.placeholder.com/150?text=back'
expect(page).not_to have_selector('img[data-async-image-url-value="https://via.placeholder.com/150?text=front"]')
expect(page).not_to have_selector('img[data-async-image-url-value="https://via.placeholder.com/150?text=back"]')
# adding sleep to allow turbo_stream the ability to load before the broadcast happens.
# without this, broadcasting happens before the ws connection is established.
# sleep 0.25
design.update(front_image_url: front_url, back_image_url: back_url)
design.broadcast_replace_to(
design,
:previews,
target: "design_#{design.id}_previews",
partial: 'dashboard/handwritten_designs/previews'
)
expect(find('img[data-async-image-url-value="https://via.placeholder.com/150?text=front"]'))
expect(find('img[data-async-image-url-value="https://via.placeholder.com/150?text=back"]'))
I originally thought that this was a capybara waiting problem but apparently, this flow results in broadcast firing before turbo_stream_from can establish the connection. (notice the broadcast log happening before the connection registered)
You could change it to test the original flow of the page by filling out the form and submitting to the controller that way it will have to load the page first and it will more accurately test the functionality
I have yet to find a better solution That said, as we’re continuing to add more and more Turbo streams in we are hitting more and more random test failures like this. So we’re going to have to come to a solution at some point. Can’t just continue to sleep the for all of our system specs
This has been the main solution we’ve decided good be the best solution at this point. That said, it feels so annoying to check for this in all of these tests. It goes back to that dirty feeling that I’m just writing code to make tests pass. Again it’s fine if that’s the only solution, but doesn’t feel great imo.
Hey there, has this been working for you to avoid flaky tests?
The solution I did was return turbo_frame in the response on the action and trigger broadcast. This seems to make things work a bit better since it doesn’t rely on the turbo stream to be setup.
I’ll likely ask if this is okay in another thread.
has this been working for you to avoid flaky tests?
All the solutions that I provided or tried above unfortunately did not work out well and were still prone to intermittent failures. Other than adding the sleep if I remember correctly (I’ve moved on from day-to-day on that project).
The solution I did was return turbo_frame in the response on the action and trigger broadcast. This seems to make things work a bit better since it doesn’t rely on the turbo stream to be setup.
Interesting, and you’d say that it consistently works? I read through your other post but I’ll be honest I think I’d need a bit more context with the code. For example, was that just a partial being rendered in another view or something?
Your comment prompted me to look deeper. It turns that it wasn’t that I added a process jobs to the test, it was that I added a turbo_stream_from on my component under test.
My context is that I am system testing a viewcomponent, and I had to render that view component in a template in order to do some stuff (it’s a bootstrap modal, so I had to programmatically display it after render). For me, it was the case that in a test context, there was no turbo stream connected in the view, so my controller broadcasts were being shot into space.
I was able to get the test working without using the jobs helper. Not sure if that is applicable for your situation. Unfortunately for us, we are using a few libraries on the frontend for this feature that aren’t Rails native so having those libraries support Turbostreams was more work than using broadcasts.