How to run one Cucumber (With Protractor) scenario over multiples files? - protractor

I have a Cucumber feature like this one:
#MainSuite
Scenario: Verify that user can login
Given I can see the login form
Then I set a username
And I set a password
And I click in Login button
Then I see the "wrong-password" message
I need to check that the user can login in 5 different pages.
I need to run that feature in 5 different places.
It's like, I need to run that feature in /login.html, /old_login.html, /after_restore_password.html and more (it's just an example).
Do you know how to do it?
Currently, I have only one file hardcoded. Obviously I need to change it.
this.Given(/^I can see the login form$/, function(done) {
this.goTo('login.html');
browser.wait(EC.visibilityOf(this.loginFormContainer));
done();
});

Create an object containing the different login pages that you can go to.
Include an if statement in your step def if there is any extra code that needs to be executed.
this.Given(/^I can see the "(.*)" login form$/, function(loginPage, done) {
var logins = {
login : "login.html",
afterpasswordreset: "after-password-reset.html"
}
loginPage = loginPage.toLowerCase().replace(" ", "");
this.goTo(logins[loginPage]);
browser.wait(EC.visibilityOf(this.loginFormContainer));
done();
});
Make either separate Scenarios or feature file for each variation of login, or simply create a Scenario Outline for them
EDIT
Here is how I would implement the Scenario Outline:
#MainSuite
Scenario Outline: Verify that user can login
Given I can see the "<loginType>" login form
And I set a username
And I set a password
When I click in Login button
Then I see the "wrong-password" message
Examples:
| loginType |
| Login |
| After Password Reset |

Related

Pytest-bdd giving an name error for variables defined in scenario outline

I am trying to run a test with ptest-bdd. I've used the scenario outline but the variable username is returning a name error saying that username is not defined. I would greatly appreciate a second pair of eyes on my code.
Here is the feature file:
#login
Feature: Valid Login
As a employee,
I want to login to my account
So I can access the application
Background:
Given the login page is displayed
Scenario Outline: Manager enters correct login credentials and Ok button
When the user enters their <username> and <password> correctly
And the user clicks OK
Then the page redirects to the manager home page
Examples: Manager
| username | password |
| fake_name | 1234 |
And here is the test_login_steps.py code:
from pytest_bdd import scenarios, scenario, given, when, then, parsers
from pages.signin import QaSigninPage
from pages.managerHomepage import QaManagerHomepage
import pytest
CONVERTERS = {
'username': str,
'password': str,
}
scenarios('../features/login.feature', example_converters=CONVERTERS)
# Create Page Objects
#pytest.fixture(scope='session')
def pages(test_manager):
pages={"signin_PAGE": QaSigninPage(test_manager.browser),
"manager_home_PAGE": QaManagerHomepage(test_manager.browser)}
return pages
# Given Steps
#given('the login page is displayed')
def login_visit(pages):
pages["signin_PAGE"].load()
#when('the user enters their <username> and <password> correctly')
def enter_credentials(pages):
pages["signin_PAGE"].enter_username(username)
pages["signin_PAGE"].enter_password(password)
I forgot to pass the variables into the function... I figured it out.
When you are using CONVERTERS use scenario in place of scenarios, which allows you to pass examples as parameters

How to define before tag for only one scenario/feature from more ones

I need to run one before tag for specific scenario. How to do that?
So I have one scenario where I need to set up some request like user no.1. I have my one token getting from system based on provided username and password. This is all set up in before tag in hook file - code no.1
Then I need to run another before tag in hook file to get token as user no.2 different user and finish this task. code no.2
I am not able to differentiate it or my system still gets new token like to be always user no.1
code no.1 - it runs each time
Before(async () => {
const page = World.page;
const token = retrieveToken();
console.log('Using environment url: ' + EnvironmentVariables.URL);
await page.goto(EnvironmentVariables.URL + `/?access_token=${token}&expires_in=3600&token_type=bearer`);
await page.waitForSelector(SelectorUtils.nameSelector(NavigationComponent.searchClientInputName));
await waitForSpinnerToEnd();
});
code no.2 - here I am trying to use annotation with name of scenario but with no effect. I get token but when I look at console I see login details from code no.1
Before({tags: '#SubmitSRForReviewFinish'}, async () => {
const page = World.page;
const token = retrieveTokenLogin();
console.log('Using environment url: ' + EnvironmentVariables.URL);
await page.goto(EnvironmentVariables.URL + `/?access_token=${token}&expires_in=3600&token_type=bearer`);
await page.waitForSelector(SelectorUtils.nameSelector(NavigationComponent.searchClientInputName));
await waitForSpinnerToEnd();
});
I need to be able to run before tag only for specific scenario. How to do that? How to log with another scenarion as another user?
SOLVED:by myself
SOLUTION:this solution with annotation works but you need to remember that if you have some beforeAll tag where you set up window and other properties once at the beginning you need to change it to only before tag cause your browser window is still open and no matter what it still gets old values.

Drupal - Dynamically login user inside multistep form and refresh user menu

I have an ajax multistep form in D7.
When users try to reach step-4, if they are logged-in, they can go on with the form, otherwise they have to login.
In this specific case is not accettable that users "leave" multistep form before the last step, so no redirection to user/login is possible.
What I've done is to try to replicate the login form inside the multistep form and on submit to dynamically login user.
if(isset($form_state['values']['step_4']['user'])){
$uname = $form_state['values']['step_4']['user'];
}
if(isset($form_state['values']['step_4']['password'])){
$password = $form_state['values']['step_4']['password'];
}
if (($uname != '') && ($password != '')) {
if($uid = user_authenticate($uname, $password)) {
global $user;
$user = user_load($uid);
$arr = array ('name'=>$uname,'pass'=>$password);
user_login_finalize($arr);
}
else form_set_error('step_4', t('Wrong Username'));
}
This code works, and user is logged-in, but there are 2 big problems that I can't fix and suppose that aren't fixable:
1.After login, step4 is loaded with an error message that says "form session expired", probably because user is "changed". I'm pretty new to Drupal so I really don't know how to handle this.
2.User menu, logically is not updated, and I can't find documentation on how to dynamically "refresh" it.
Any help is really appreciated.

Testing stateful Mojolicious apps

I want to test hiding and unhiding of an entry. I conduct the following tests in Mojolicious t/basic.t:
my $t = Test::Mojo->new('AdminApi');
$t->get_ok('/publications/hide/1');
$t->get_ok('/read/publications/meta')->content_unlike(qr/Paper with id 1:/i);
$t->get_ok('/read/publications/meta/1')->content_like(qr/Cannot find entry id: 1/i);
$t->get_ok('/publications/unhide/1');
$t->get_ok('/read/publications/meta')->content_like(qr/Paper with id 1: <a href/i);
$t->get_ok('/read/publications/meta/1')->content_unlike(qr/Cannot find entry id: 1/i);
My problem is that the two lines '/publications/hide/1' and '/publications/unhide/1' do not hide and unhide the entry. The state of the entry remains untouched.
If I repeat the steps manually in the browser everything works well. For the obvious reasons I want to have it automated with the tests. How to do this?
EDIT: The calls '/publications/hide/1' and '/publications/unhide/1' change the state of the database - just a simple UPDATE query. The change applies to the whole application - for all users. But one needs to be logged in as a user to hide/unhide. Question: how do I emulate a logged user during the test?
Contents generated by '/read/publications/meta' and '/read/publications/meta/1' can be read without login.
Bitbucket Repo
File with test code: basic.t
As you have already said, you need to be logged in to perform the hide and unhide action.
my $t = Test::Mojo->new('AdminApi');
You are creating a new UserAgent here. The Test::Mojo class inherits from Mojo::UserAgent. It has a cookie_jar and thus keeps a session alive. You need that to perform this action:
$t->get_ok('/publications/hide/1');
But right now you are not logged in. What you need to do is log in the user. Looking at the code in your repository, you actually assert that you are not logged in.
$t->get_ok('/')->status_is(200)->content_like(qr/Please login or register/i);
Before you perform the hide, you need to log in the user. After digging a bit in your code I found the action and the template to do that, so I know what the request needs to look like.
$t->post_ok(
'/do_login' => { Accept => '*/*' },
form => { user => 'admin', pass => 'hunter2' }
);
Now your $t UserAgent should be logged in and you can do the hide. Note that get_ok only checks if there was no transport error. So in fact it would make sense to now check if in fact you are now logged in.
You could do that by introspecting the session in the application, by checking the logfile (you are writing "Login success" there) or by checking the page for some string that says that the user is logged in. In templates/display/start.html.ep there is a text that welcomes the logged-in user, so you can use that.
$t->post_ok(
'/do_login' => { Accept => '*/*' },
form => { user => 'admin', pass => 'hunter2' }
)->text_like(qr/Nice to see you here admin/i);
Because text_like uses the text-nodes, the <em> around the username is not relevant in the test.
Right, now we know you are logged in. Time to switch the thing on and off.
$t->get_ok('/publications/hide/1');
Because there is no obvious error thrown for that as far as I can tell, I don't see how to test the success of that. Status code is one way, but there might be something in the content as well that you could test.
To verify the state of the application, you would now call the publication.
$t->get_ok('/read/publications/meta')->content_unlike(qr/Paper with id 1:/i);
$t->get_ok('/read/publications/meta/1')->content_like(qr/Cannot find entry id: 1/i);
Right. But remember, our $t is still logged in. Maybe the logged-in user is allowed to see hidden stuff as well as unhidden stuff. Maybe they are not.
It's probably safer to make a second UserAgent that's not logged in, and check with that one as well.
# check with an unauthorized user
my $t_not_logged_in = Test::Mojo->new('AdminApi');
$t_not_logged_in
->get_ok('/read/publications/meta')
->content_unlike(qr/Paper with id 1:/i);
$t_not_logged_in
->get_ok('/read/publications/meta/1')
->content_like(qr/Cannot find entry id: 1/i);
Now basically you repeat the same thing by unhiding your content and testing again. Rinse and repeat.
Keep in mind that unless you are using an explicit testing database (which you seem not to do), you cannot be sure that there even is an entry 1. Or what the name of that is. You should use fixtures for the tests. You could, for example, create a fresh instance of the DB using sqlite and work with that.

GAS - setTag() - getTag() still not working

I'm creating a webapp which allow :
to log using data stored in a spreadsheet (login and password)
to add some data to this spreadsheet (bet on rubgy matchs)
My problem is to recognize which user is connected.
What i did so far
in the doGet function, where all panels except connection are invisible, I created a label where i'll store the login into the tag
var loginlabel=app.createLabel().setId('loginlabel').setText('test').setVisible(true);
in the connection, I store the login into a invisible label tag
var logintest=e.parameter.logint;
app.getElementById('loginlabel').setTag(logintest);
I want to allow people to change their own password (but I also need to retrieve the login name for other purposes, but let's take this one
When I click on "Modify password" button, I want to get the Tag, but I always get a NULL
var login=app.getElementById('loginlabel').getTag();
I'm free to share my code here or wherever
Maybe it does exist other way to do this, I'm open for advice
In a server handler you can get the tag value using
var tagValue = e.parameter.loginlabel_tag ; // assuming the label has a name = 'loginlabel'
Note that the widget must have a name to be able to retrieve the tag value (see this post among others)