cucumber + capybara step definition - sending POST requests - ruby-on-rails-3

i have the following step definition:
When /^I upload it$/ do
end
which relates to a file upload. the visit method in capybara, from what i can tell is a GET only method .. and the only way to do a POST request is by implementation:
visit "/files/new"
within('#upload-form') do
attach_file('File', #files_path+'/file.txt')
click_button('Upload')
end
this doesnt seem a very strong test, as its dependant on the HTML and form tags within the files/new template.
is there a better way to handle this, or is this OK to do? i had in mind something like this:
post files_new_path { file: => 'a_file_on_the_system.txt' }
but then again cucumber tests are integration tests .. so which is the 'official' or best way to write tests at this level?

The Capybara codes mimic human actions. You can't expect human to "POST" but only "visit", "click_button" etc.
The syntax you mentioned would fit controller test better, but not integration test with Capybara.
The best style in integration test, in my opinion, is to think and act like human being but not machine.

Related

Is it possible to call a test feature from a MockServer feature(matched) in KarateDSL?

I'm trying to do something that I don't know if it is even remotely possible or not.
I've a Mock server, and I'd like that when it receives a given request, it "starts another test", calling a test feature. I tried some stuff, including the one bellow. But turns out that this Mockserver scenario do not respond.
Scenario: pathMatches('/ideas')
* def xx = call read('SimpleStart.feature')
* def response = $ideas.*
Is there an elegant way to make this work? AN workaround or a suggestion you can give me?
The use case is:
Perform tests, some tests, make some external services invoke the mockserver, and if the mockserver is requested it triggers other tests.
Thanks in advance.
Yeah Karate certainly isn't designed to do that. The pattern should be set up your mocks and tests from a Java "runner" for maximum control and that's what most teams do.
In short, "orchestrate" things from Java code.
That said, see if this gives you some other creative ideas: https://twitter.com/getkarate/status/1417023536082812935

Cypress tagged hooks with mocha

I have been building ui automation frameworks with Cypress for some time, but always using the Cypress-Cucumber-Preprocessor.
Now I need to build one without cucumber, just plain ol' mocha, but I found a problem. Seems like I can't use tagged hooks to execute code for specific tests (scenarios in Cucumber)
The scenario is basically this. I have a spec file with several tests. I have a "before" hook that seeds test data to a Mongo db, and eventually I might need to add a hook or hooks to execute something (whatever) before a specific test.
With Cucumber you have a way to tag a given scenario (#tag) and then you can create a hook that will be executed ONLY before or after that specific scenario
#tag
Scenario: Tagged scenario
Given condition
When I do this
Then I should see that
before({tag : '#tag'}, () => {
code
})
I haven't found a way to do this with mocha in Cypress... Anyone has found a way?
thx
You can use BeforeEach or Before, that does predominantly the same thing in Mocha.

Selenium, questions about code re-factoring

With Selenium IDE I generate a sample script for test the log to a website and a value in the website after logging. So my script is (Java) :
#test
public void mytest() throws Exception{
// Load the home page
...
// complete the log form
...
// check if the log work
...
// Logged : click on some element in the page
...
// Logged ; check the information X (if one HTML element contains child or not
...
}
I use JUnit for run the test class from a main class. My question is : What is the best way for re-factoring my code ? I would like create one class by "step", is it possible ? by example :
Class for load page and check there isn't error 404
Class for complete the log form, submit and check if the user is logged
Class for navigate in the website and get the information I want
Is it the best way? There isn't a real goal. Just, I want know how organize the code for a maximum of reuse (sorry for my bad English x) )
There are couple of reasons why you do not want to use Selenium IDE, do the recording for the test cases and refactor the code afterwards. Most of the time selenium IDE will provide you the selectors that are not stable enough. For rerunning the tests you want to make sure the selectors are stable enough and will not possibly depend on html structure. Second, as the test suite getting larger you want to reduce the code duplication as much as possible. Using Selenium IDE there is no way to understand which code blocks can be reused.
So, bottom line is for a good test suite start building a framework from scratch instead of using Selenium IDE. There are a lot of example out there how to start. I have one with TestNG here if that helps.

Modify an http response in a protractor test

I'm trying to write some end to end tests for our application's login process, but am having trouble getting my head around the best way to set up the scenario where the user needs to change his password.
When our server responds to a successful login, a user object is returned with a changePassword field. The client then inspects the response and redirects accordingly.
My problem is getting the test set up so that the changePassword field is set - what is the best approach to use?
I see my options as:
Have a test set up and tear-down script for the server that creates a brand new user specifically for the test run with changePassword flag set in the database.
This seems like the most end to end approach, but is probably also the most effort & code.
Somehow intercept the http response in the test and modify the changePassword flag to be set for this test only.
Mock the http response completely. Using this approach is the most removed from an end to end test, but is perhaps the simplest?
Which is the best or most common approach? Also any general pointers on how to actually implement the above (particularly 1 and 2) with protractor would be great - I'm finding it hard to conceptually get straight in my head, and hence hard to know what to search for.
I'm using protractor as the test framework, with angular.js powering the client side, and a node server running utilising (among other things) express.js and mongoDB.
Having thought about this further, option 1 is the best solution, but is not always possible.
Option 2 is also possible, and option 3 should be avoided.
For option two, a mock module can be created like so: (coffeescript)
e2eInterceptors =->
angular.module('e2eInterceptors', [])
.factory('loginInterceptor', ()->
response: (response)->
# Only edit responses we are interested in
return response unless response.match(/login/)
# do the modifiations
response.data.changePassword = true
# return the response
return response
)
.config(($httpProvider)->
$httpProvider.interceptors.push('loginInterceptor')
)
You can then inject this module into your tests using
browser.addMockModule('e2eInterceptors', e2eInterceptors)
If you want to do this globally, you can put this in the onPrepare function in your protractor file, otherwise just call it when needed in tests.
I think your first approach is the most appropriate.
It would be useful anyway to test the new user creation, so it is not a waste.
And for example this example seems to be something similar: http://product.moveline.com/testing-angular-apps-end-to-end-with-protractor.html

How can I stub a controller/current_user method in Capybara acceptance test

I have a helper method that calls current_user.eligible_for_reward? and I want to stub that call in a Capybara acceptance spec. In my model I have a placeholder dummy method:
User.rb
def eligible_for_reward?
"blah"
end
Here is what I've tried so far:
I tried stubbing current_user, but that results in a "modify frozen object" error because controller is nil. I believe controller will only be set if I use RSpec's get instead of visit some_path. I need to stick with visit some_path, I believe, otherwise my page.should ... all fail because page is not set.
I tried logging in as user (login_as(user) which successfully runs through the register/login) and then stubbing user.eligible_for_reward?, but that doesn't seem to work, as I'm still getting back the test "blah"
Is there a good way to stub out this method?
Stubbing in acceptance specs is not a good idea. If there is no other way then you can just do:
User.any_instance.stub!(:eligible_for_reward?).and_return(true)
Just remember that stubbing/mocking things in acceptance specs means that you really don't test anything.