0
votes

I'm having trouble attaching a file using Minitest with Capybara in Rails. The problem is that the file field is in a nested form. The nested form gets a random ID and name added to it, so I can't select by these.

Normally when it's not a nested form this works:

attach_file("post[featured_image]", "#{Rails.root.join("test/fixtures/files/example-featured-image.jpg")}")

But, on the nested form the form field looks like this:

enter image description here

I thought this should work:

within(".image-upload") do
  attach_file('input[type="file"]', "#{Rails.root.join("test/fixtures/files/example-featured-image.jpg")}", make_visible: true)
end

But that gives me this error:

Minitest::UnexpectedError:         Capybara::ElementNotFound: Unable to find file field "input[type=\"file\"]" that is not disabled within #<Capybara::Node::Element tag="fieldset"

I've also tried other methods described in the capybara docs here.

Is there a way to do this? The only time I've gotten capybara attach_file to work is when I've been able to target the element name as in the post[featured_image example above.

1

1 Answers

1
votes

You're not showing enough HTML to confirm that the input field is actually within the .image-upload fieldset, but assuming it is then it's possible the real file input is actually hidden, and replaced with something else for styling purposes. Additionally the locator passed to attach_file is not CSS it's the id, name, or associated label text (ie 'input[type="file"]' is not valid there). Given all that there's a number of things you could do

If the file field is visible and the only one in scope then skip the locator

attach_file(Rails.root.join("test/fixtures/files/example-featured-image.jpg"))

If it's visible and there are multiple in scope then pick the one you want using name or id filter, potentially with a regexp

attach_file(Rails.root.join("test/fixtures/files/example-featured-image.jpg"), id: /images_attributes_0_image_file/)

If the file field is actually hidden then try

attach_file(Rails.root.join("test/fixtures/files/example-featured-image.jpg")) {
   # do whatever the user would do to initiate selecting a file
   # click('Upload File') - etc
}

That would be emulating the user as much as possible - if that doesn't work then another approach would be to attempt to force the file input to be visible like

attach_file(Rails.root.join("test/fixtures/files/example-featured-image.jpg"), make_visible: true)