LuckyFlow is automatically installed and configured with Lucky projects
(excluding projects generated with the
For tests to run you will need to install Chrome and Chromedriver:
brew cask install chromedriver
sudo apt-get install chromium-chromedriver or
LuckyFlow provides methods for visiting pages, clicking and interacting with elements, and filling forms.
When writing flow specs, it’s best to write the spec as a full flow that a user might take. For example, here is a flow for publishing an article:
# spec/flows/publish_post_spec.cr describe "Publish post flow" do it "works successfully" do flow = PublishPostFlow.new flow.start_draft flow.create_draft flow.draft_should_be_saved flow.open_draft flow.publish_post flow.post_should_be_published end end
Then create a Flow object that performs the interactions and assertions:
# spec/support/flows/publish_post_flow.cr class PublishPostFlow < BaseFlow def start_draft visit Articles::Index click "@new-post" end def create_draft fill_form SaveArticle, title: "Draft Post", body: "body" click "@save-draft" end def draft_should_be_created draft_title.should be_on_page end def open_draft draft_title.click end private def draft_title el("@draft-title") end def publish_post fill_form PublishArticle, title: "Published Post" click "@publish-post" end def post_should_be_published el("@post-title", text: "Published Post").should be_on_page end end
You can visit pages with some built-in methods that accepts strings and Lucky routes.
# Visit an action that does not need params visit Home::Index # Visit a route that takes params post = PostBox.create visit Posts::Show.with(post.id)
asto sign users in
Lucky comes built-in with a backdoor in tests so that you don’t need to go through the full process of loading the sign in page and filling out the form. Instead you can use the
as option to visit the page and sign the user in automatically:
user = UserBox.create post = PostBox.create visit Posts::Show.with(post.id), as: user
Check out the
Auth::SignInThroughBackdoormixin to see how the backdoor works.
You should generally use Lucky routes but if you need to you can use strings to visit a path
You can work with elements using the
Note that finding elements with
el is lazy. That means that when you call
el it will not fail if it can’t find an element, because it won’t try to
find the element until you try to interact with it or check if it is in the
@to find by Flow ID
If you are familiar with other libraries for interacting with pages, you likely have found elements using CSS or by the text inside of elements. This can be brittle because CSS and text can change and then break your tests even though the feature still works.
Instead of using CSS or text, you can use the special
@ selector for
interacting with elements. This uses an HTML attribute called
# Looks for an element with an HTML attribute called "flow-id" # with the value "view-posts" el("@view-posts")
Using this in a Lucky page is simple:
# LuckyFlow will find this element link "View Posts", Posts::Index, flow_id: "view-posts"
You can also find elements by CSS, but using Flow IDs is preferred because your tests will be more resilient to change.
In the cases when you do need to use CSS, here’s how you would do it:
# look for an anchor tag with the "post-title" class el("a.post-title") # look for an element with an id of "post-button" el("#post-button")
Sometimes you want to only find elements that contain certain text. Use the
el("a.post-title", text: "Title of post") el("@post-title", text: "Title of post")
el("@save-button").click el("a.post-title", text: "My title").click # Or use the shortcut method `click` click "@save-button" click "a.post-title"
Fill forms rendered by Lucky:
fill_form SavePost, title: "My Post", body: "Post body"
You can also fill forms based on the input’s
fill "post:title", with: "My Post"
Or use the
fill method on an element:
You can use
el combined with the
be_on_page matcher to assert that an
element is on the page:
el("@post-title", text: "My post").should be_on_page