Handling standard user facing scenarios - javascript

*I was wondering if i could do all these in javascript, as opposed to having rails helpers
In my application, there are several types of "if-else" UI cases. This is a fairly common scenario, and i wonder if anyone has a tidy way to do these?
EG 1) There might be several types of links with the same behavior: "upvote", etc.
If it is the user's own article, i do not want it to be passed to the server, but pop up a dialog box
EG 2) There might be a several links called "follow", "become a fan", etc
If the user already have done the given action before, it should be a text "followed" instead of a link.

Normally you'd use helpers for this. You write helpers called, based on your examples, upvote_button (which might take a user as a parameter) or follow_button (where this one might take true/false for already-following/not-following.
If you can be more specific as to what you need, I can probably be more specific in my answer.

Related

Page Object Model or JavaScript testing alternatives?

Is the Page Object Model still the best way to automate web applications ?
For me the Screenplay pattern seems a nicer way to manage it.
Or using JavaScript alternatives like Acceptance Testing with Cucumber.js & WebdriverIO for example.
Your question makes it sound like there is only one answer, but actually you can merge these all together if you code it correctly.
Page Object Model
This is good for separation of the elements on the page from the rest of your code. If implemented correctly, a change on the page can be corrected for all scenarios using that page by simply changing one line in the POM.
nextButton.click();
fullName.sendKeys("John Doe");
Screenplay Pattern
This is good for separation of actions that occur on the different pages, the different workflows.
james.attemptsTo(
goToTheNextPage(),
fillOutHisDetails()
);
If the journey has workflow that is slightly changed, the idea is that you can simply reorder the Screenplay pattern, or remove the actions that are no longer necessary.
In the example above, if the business were to decide that the registration form should be a single page instead of multiple, it would make more sense to delete this single line:
goToTheNextPage(),
instead of deleting the 2 that I would have put in:
driver.findElement({css:"#next"}).click();
driver.findElement({css:"#registrationDetails"});
CucumberJS + WebdriverIO
This is good to portray the information of a scenario in pure business language.
Scenario: I am filling out the registration form
Given I am a new user
And I want to register for an account
When I fill out the registration form
Then I should be able to log in
Merging them
If you want truely human readable code, you can merge all 3 of these.
You have your feature file at business level language.
You have your step definitions written with the Screenplay pattern in mind.
You have the Screenplay pattern steps written with the Page Object Model.
This may seem like a lot of layers, but it means that the business will be able to understand the scenarios, the testers and developers looking back over the code will understand the workflow of a certain journey, and looking further into the code on debugging will allow the tester to change the element values across multiple journeys by only changing one line of code.

Gherkin - maintaining state between scenarios

Although I have been writing unit tests for 20-odd years, I am new to Gherkin, and haven been given the task of implementing a story for a .feature file that reduces to something like this:
Scenario: a
Given that the app is open
When I open a certain dialog
Then it has a thing somewhere
Scenario: b
Given that the dialog from 'a' is open...
# Imagine here a long chain of scenarios, each depending on the previous
Scenario: n
Given that the previous 'n' steps have all completed....
That is, a long, long chain of scenarios, each depending on the state of the system as configured by its predecessor.
This doesn't feel right to someone used to unit testing -- but these scenarios are not going to be split and run separately.
What's the best practice here?
Should I rewrite into one very long scenario?
I am already using a 'page object' to keep most of my code out of the step definitions -- should I be coding the steps as single calls, that can be re-used in the later scenarios?
I'm running Cucumber in Javascript.
First things first, Warning:
For the majority of tests (and by majority I mean 99.9% of the time), you should not carry on from the previous scenario, because of the fact that if one scenario fails in your feature, more will crumble because you attempted to string them together.
And on to my answer:
Depending on whether you are trying to do a set up for all of your scenarios after (within the same feature), or whether you want to reuse that first scenario multiple times (in separate features), you could do one of 2 things.
Make the first scenario a background
Make the first scenario into a step definition, for use in multiple feature files
For the First:
Background:
Given that the app is open
When I open a certain dialog
Then it has a thing somewhere
Scenario: a
Given that the dialog from 'a' is open...
Just remember that when you use it as a background, it will be used for all the following scenarios within that feature.
For the Second:
Scenario: a
Given that the app is open
When I open a certain dialog
Then it has a thing somewhere
Scenario: b
Given I have opened the dialogue from a
And the '<DialogFromA>' dialog is open...
I would ask myself, what is the actual behaviour behind all the steps?
Then I would implement that as the wanted behaviour and push the order between steps down the stack. Probably using one or many helper classes. There is nothing saying that you can force the order of the scenarios without introducing some hack to force them together.
Remember that BDD and Cucumber is all about human readable communication. The dependencies you are asking for should, in my opinion, be implemented in the support code Gherkin triggers.

Best way to detect browser state changes

And with state I mean URL changes, preserving browser history.back() and being able to update the page (through a callback I guess) when there is any change.
I've tried several methods, and each one has its pros and cons.
For example, I like the way Backbone.js manages the URLs with its Router because it works via the window.location.hash (#) and if you change the URL manually it's catched by the Router allowing you to perform manual changes in an easy way.
The thing I don't like about Backbone is the URLs being in this format "#/a/b/c/d/e" (against the classic http standard "?a=1&b=2&c=3". That means that the URL parameters needs to be in certain order and they don't have name. Of course you can fix that parsing the URL and treating the Router expression as a single string, so it's not a big problem.
Also, I think using Backbone just for its Router it's a bit overkill (including the whole BackBone just for that), so I'd like other solutions.
The next one is History.js, which is supossed to provide compatibility for the new HTML5 standard?
But I don't like its behaviour as much as the Backbone's one. I mean, in an HTML5 browser, the # is converted to ? and if you change something in the URL the whole page is reloaded.
Also, due to its lack of Router, you need to set some more listeners, like $(window).bind('statechange') and $(window).bind('hashchange'). Again this is not a big problem, but I'd like to know if there are other ways to do this.
I always say that "there's no a right way to do something, but different ways to achieve it". But to be able to choose one of that ways, I'd like to know about different possibilities.
What do you think about this problem, which is more and more common when developing Single Pages?
I've researched a bit, but all the answers I found are quite old (> 1 year+) so I'm interested on the state of art...

Passing Arguments via ajax - Correct Markup

I am putting together a front end for a shopping basket, and it uses a Javascript API to communicate with the database. I have methods such as:
updatePackageQuantity
updateProductQuantity
removePackage
reinstatePackage
Each of the methods require various arguments to be passed, and I'm currently figuring out the best way of retrieving them from the page and passing them.
For example, I currently use classes like this:
Update Quantity
and I'd grab the value from the input field in this instance. I also have 'constants' that I need to pass such as basketID, shopID etc, and I'd like to be able to grab them from the markup somehow.
What would be the ideal way of achieving this? Maybe having a hidden form on the page with a list of inputs, or could I attach the values to attributes, similar to the way its done on twitter bootstrap:
Follow #twbootstrap
I notice they use a lot of attributes prefixed with 'data-'. So what's the right way?
Well..
I believe going with the "data-" attributes would be best, since its a nice little nifty feature of HTML5.
Also, it'll keep your markup clean.
So if you think your application would be running on Modern browsers, this should be the way to go.

Voting with Ajax in Rails

I'm trying to allow users to vote a record up/down with Ajax. I'm using the vote_fu plugin for the voting functionality, and everything works fine without Ajax. I'm now trying to figure out the best way to implement the asynchronous functionality with unobtrusive javascript.
What I'm doing now is having two buttons, "Up" and "Down", such that when you click either one, a request is made to votes_controller and the create or update action, depending on if the user had already submitted a vote on that record before. The params submitted would be the record_id as well as the value of the vote.
With Ajax, how should I handle the case where a user enters a page to vote without having voted on the record before? Specifically, the links would go to the votes#create in the beginning, but after that first submission, the links should switch to votes#update.
Is there a standard way to take care of this? I was thinking about just adding an extra check in the "create" method such that it would act like "update" if it found a record for the user_id, voteable_id pair, but this seemed kind of clumsy and not fully RESTful.
Thanks,
Eric
There are several techniques/patterns commonly used:
1) When your erb creates the page, you can supply a parameter to the JS script that is a part of the page. The parameter will be the "voting_url" it will be either votes/new or votes/123 depending on whether a create or update operation should be used.
2) You could use a "procedure call" as opposed to a rest call. The procedure/action would be "change_vote" -- with a param of 'up' which would be either true or false. The action would create the vote record if needed, or would otherwise modify it.
3) As part of the creation process of the main record, you could always create the vote_record. That way, the voting operations would always be updates since the vote_record will always already exist.
Added
Re: comment of when is it generally "acceptable" to move away from a rest call?
Rest is a design philosophy. It solves a lot of problems but doesn't fit all situations. I'd think that your original question would be ok but ultimately it is up to you and whomever reviews your architecture. Since it is possible to "bend" your app into a rest api for this function, some might tell you to do so--to thereby gain the benefit of not violating Restfulness.
Re: your example in your comment about friend relationships:
Since it makes sense to "create a friend relationship" it'd be better, other things being equal, to express the api as a rest "friendship object/create" call. It was exactly for your friending example that rest was created. -- The old style alternative is that each api developer had to figure out a large set of procedure names.
Rest provides a more consistent, standard way of creating the names.
Note that a "change_vote" procedure would be best defined as part of the votes object: either votes/change_vote or something similar. I believe that there is a "Rails way" for urls for rest procedures that don't fit the standard rest verbs.
Another idea would be yo change the url (through a helper probably) depending if the record is a new one.
Something like:
link_to_remote "Up", :url => voting_path(#vote)
module VotesHelper
def voting_path(vote)
if vote.new_record?
new_voting_path
else
edit_voting_path(vote)
end
end
end

Categories