Little late in answering this, but maybe this will help someone else down the road. I gave long and short answers for each, if you want the quick explanation, read the TLDR at the end of the question, if you want a little more explanation, feel free to read in full :)
1) assert_select 'input[type=FILL_IN]'
Using either file or "file" will pass the test. According to the documentation on assert_select here: link, "The selector may be a CSS selector expression (String), an expression with substitution values, or an HTML::Selector object." Essentially, it simply needs to be a valid CSS selector, which, according to this stackoverflow post: link, depending on the situation (and it's generally not needed if it's an alphanumeric string, as is the case here), it may or may not need quotes, but it is generally good practice to use them, so that there is no potential for confusion/errors.
TLDR: using either 'input[type="file"]' or 'input[type=file]' will work in this case, but using quotes is generally considered a good practice to avoid errors.
2) post microposts_path, micropost: { content: content, picture: FILL_IN }
For this one, as @Nick mentioned, you probably want to just use the variable 'picture' that was created on the line above the line with assert_difference. Remember that when you added the picture attribute to the micropost model, you ran the command:
rails generate migration add_picture_to_microposts picture:string
which would mean that it's expecting you to pass a string, not a boolean, when creating a micropost. Also note what the test is actually doing:
assert_difference 'Micropost.count', 1 do
post microposts_path, micropost: { content: content, picture: FILL_IN }
end
The code is actually creating a micropost by posting to the microposts path, and then checking to make sure the count increased by 1.
Now, you might be saying: but the picture variable isn't a string! This is true, and I'm not an expert on CarrierWave and I haven't really dug into its code, but it seems like it's actually expecting a file path and a MIME (file extension) type, based on the documentation for fixture_file_upload, found here: link. If you remember from the tutorial, you added the line:
mount_uploader :picture, PictureUploader
to your microposts model, which appears to be associating the picture attribute with the PictureUploader class (found in app/uploaders/picture_uploader.rb), which has the following in the class file:
class PictureUploader < CarrierWave::Uploader::Base
which means it's inheriting from the CarrierWave::Uploader::Base class, which probably means that CarrierWave is messing with the picture attribute to take something other than a string (which as I mentioned, it appears it takes a path and a MIME type based on the documentation), but a boolean won't work. (For the record, I did some testing, passing in a random string and then a random file path, and both failed as expected -- and so did passing a boolean).
Also, and admittedly it's a small detail, but even if passing in a boolean worked, it would only generally test for it being a picture, as opposed to a particular picture, which would be another argument for using the picture variable.
TLDR: you should probably just use the picture variable: post microposts_path, micropost: { content: content, picture: picture }
3) assert FILL_IN.picture?
You mentioned you used the code:
@user.microposts.picture?
And got a NoMethodError. The reason for this is that @user.microposts will return a collection of microposts, not an individual micropost, and so it is confused (specifically, it returns an ActiveRecord_Associations_CollectionProxy, which does not have a picture? method, hence, you get a NoMethodError. Also, don't forget, you can open up the rails console, and run User.first.microposts.class to find out what kind of object is being returned by @user.microposts). Remember that the picture? method only works on an individual micropost, so you'll want to do something like:
@user.microposts.first.picture?
which will check the most recently created micropost (microposts are sorted by the date/time they were created, with the most recent being first) for a picture.
However, there is another way to go about doing it, which uses the hint Hartl gives in the exercise: "To check for a valid picture attribute, use the assigns method mentioned in Section 10.1.4 to access the micropost in the create action after valid submission"
If you remember, you can access instance variables from the controller by using the assigns method. The create action in the microposts controller has an instance variable @micropost, which will be the most recent micropost created by the user as well.
The code would look like:
foo = assigns(:micropost)
assert foo.picture?
In fact, you can prove to yourself that both methods would work, by adding the following code:
foo = assigns(:micropost)
assert foo.picture?
assert @user.microposts.first.picture?
assert_equal foo, @user.microposts.first
So what this code does is the following: first, it creates a variable foo and assigns the newly created micropost to it. It then checks that foo.picture? is true, and then checks the other method, @user.microposts.first.picture? and checks that it's also true. Lastly, it checks that foo and the most recent micropost for @user are the same thing, and all of these tests should pass.
TLDR: you were calling the picture? method on a collection of microposts, not an individual micropost. You can use either @user.microposts.first.picture? or, if you want to use the assigns() method, you can use the that as well, with the following:
foo = assigns(:micropost)
assert foo.picture?
Hope that helps!