WebPagetest not filling in forms, gives "Navigation Error" - testing

I'm new to WebPagetest (https://www.webpagetest.org/) and am having some trouble with login forms. I am using scripting, and can navigate to the page with the form, but it appears as though I am not correctly entering any form values, nor is the form submitting.
Here is a version of my script:
logData 1
navigate https://www.example.com/secure/login
setValue name=username activation_test
setValue name=password password
submitForm id=signInForm
//clickAndWait id=signInBtn
//exec document.getElementsByTagName('html')[0].style.display = 'none';
sleep 5
block google.com/csi
navigate https://www.example.com/?jbhp=true
Of course, my first thought is to make sure that my HTML elements match, but they appear to be fine...
Username:
input tabindex="1" aria-required="true" class="success required" id="username" maxlength="64" name="username" placeholder="Email Address or Username" type="text" value=""
Password:
input tabindex="2" aria-required="true" class="success required" id="password" name="password" placeholder="Password" type="password" value=""
Form:
form action="#" id="signInForm" method="post" class="form formLarge" novalidate="novalidate"
Submit (verified within the form; only used when clickAndWait is uncommented):
button tabindex="3" id="signInBtn" class="ancBtn lrg" data-track-click="sign in : sign in" type="submit"
The result page of the test shows that it navigates to the final location as though not logged in. Also, I see this as part of the results: Step_2
(Error: Navigation Error). Sadly, if there is better documenting as to what specifically caused the navigation error, I have yet to find it.
Finally, if I switch from using "submitForm" to "clickAndWait" (which is commented out in the above example) the only difference in the result is that Step_2 shows a screenshot of the page rather than just an orange block.

IFrames. Stupid IFrames. If you find your way to my question, above, I would bet that your page has IFrames. In my case, my IFrame is coming from the same domain as the browser page -- if this is not the case for your IFrame, I'm not sure if this will work.
To access elements in the IFrame, I had to forget "setValue", "clickAndWait", and so on. I had to go straight to Javascript. Scripted, it looks something like these examples:
exec document.querySelector("iframe[id=stupidIFrameId]").contentDocument.querySelector("input[id=password]").value = 'password'
execAndWait document.querySelector("iframe[id=stupidIFrameId]").contentDocument.querySelector("button[id=signInButton]").click()

Related

Cypress doesn't find input field (maybe because inside a form?)

Page source (only iFrame part which contains to form i need to fill)
<iframe title="Form 0" id="hs-form-iframe-0" >
#document
<html>
<body>
<form id="hsForm_405e4c3f-98da-4eb1-bd27-c1886a1f811e">
<div>
<label placeholder="Enter your Vorname">Vorname</span>
<div class="input">
<input name="firstname">
</input>
</div>
</div>
</form>
</body>
</html>
</iframe>
Code i tried:
cy.get('#hs-form-iframe-0').its('0.contentDocument').should('exist')
cy.get('input[name="firstname"]').type( 'Smith') //failes as never found. Is the iFrame the cause of it? Of the form?
TLDR The correct way would be to use .find() on the iframe contentWindow.
cy.get('#hs-form-iframe-0').its('0.contentWindow').should('exist')
.its('body').should('not.be.undefined')
.find('input[name="firstname"]').type( 'Smith')
Example from Working with iframes in Cypress
const getIframeWindow = () => {
return cy.get('iframe[data-cy="the-frame"]')
.its('0.contentWindow').should('exist')
.its('body').should('not.be.undefined')
}
cy.getIframeBody().find('#run-button').should('have.text', 'Try it').click()
There are other potential problems, such as delayed loading of the iframe source. The .should('exist') check on the iframe window does not cover all situations, nor does performing visibility checks on the input.
The cypress-iframe package has a lot more checks built in, so it's a safer way to handle iframes.
You have found the iframe and access its contents but then you search for the input at the root of your DOM instead of the iframe. You can continue the chain of commands by removing the second cy.
cy.get('#hs-form-iframe-0')
.its('0.contentDocument')
.should('exist')
.get('input[name="firstname"]')
.should('be.visible') // always good to check before action
.type( 'Smith')

Best way to handle filling fields when behat testing and fields have the same name

I have a login page for a site that has three types of users. The user clicks on his/her type and the un/pw field appears, depending on whatever type the user clicks on. However, in the page source all three forms are there but two are hidden depending on which type has been selected. I'm trying to write a behat test to test logging each type of user in. My behat test looks like this:
#javascript #core
Feature: Secure Login
As a User
I expect to be asked for my credentials
So that I can use the system securely
Background:
Given I am logged out
Scenario: Failed User1 Login
When I go to user1 interface
When I submit incorrect user1 credentials
Then I should stay logged out
And I should see "The username or password entered does not match our records."
Scenario: Successful User1 Login
When I go to user1 interface
When I submit correct user1 credentials
Then I should be logged in to user1 interface
Scenario: Failed User2 Login
When I go to user2 interface
When I submit incorrect user2 credentials
Then I should stay logged out
And I should see "The username or password entered does not match our records."
Scenario: Successful User2 Login
When I go to user2 interface
When I submit correct user2 credentials
Then I should be logged in to user2 interface
When I view the page source, here's what I see for the forms:
<form id='user1' name='user1' method="post" role="form">
<input type="hidden" name="subsystem" value="user1"/>
<label for="un1" class="label">Username</label>
<div id="un_inst1"class="label_instruction"></div>
<input autocapitalize="off" id="un1" autocorrect="off" type="text" name="username" value="" style="margin-bottom: 10px" aria-describedby="un_inst1">
<label for="pw1" class="label">Password</label>
<div id="pw_inst1"class="label_instruction"></div>
<input type="password" id="pw1" name="password" style="margin-bottom: 10px;" aria-describedby="pw_inst1">
<div class="login_buttons">
<input type="submit" value="Go" class="btn_go input-submit">
<input type="reset" class="btn_reset input-reset" value="Reset">
<br/>
</div>
</form>
<form id='user2' name='user2' method="post" role="form">
<input type="hidden" name="subsystem" value="resident"/>
<div class="usr-login label">Resident Login</div>
<label for="un2" class="label">Username</label>
<div id="un_inst2"class="label_instruction"></div>
<input autocapitalize="off" autocorrect="off" type="text" id="un2" name="username" value="" style="margin-bottom: 10px" aria-describedby="un_inst2">
<label for="pw2" class="label">Password</label>
<div id="pw_inst2"class="label_instruction"></div>
<input type="password" id="pw2" name="password" style="margin-bottom: 10px;" aria-describedby="pw_inst2">
<div class="login_buttons">
<input type="submit" value="Go" class="btn_go input-submit">
<input type="reset" class="btn_reset input-reset" value="Reset">
<br/>
</div>
</form>
In my featurecontext file, I have these functions:
public function iSubmitIncorrectCredentials($interface)
{
$button ='Go';
return $this->login("tester" . time(), "bar", $button);
}
private function login($username, $password, $btn)
{
$this->fillField('username', $username);
$this->fillField('password', $password);
$this->pressButton($btn);
}
Where the $interface is for user1 or user2. The problem that I'm having is that the tests for user1 pass, but when I get to user2 tests I get this error:
{"errorMessage":"Element is not currently interactable and may not be manipulated","request":{"headers":{"Accept":"application/json;charset=UTF-8","Content-Length":"36","Content-Type":"application/json;charset=UTF-8","Host":"127.0.0.1:8643"},"httpVersion":"1.1","method":"POST","post":"{\"value\":[\"tester1479232631\\ue004\"]}","url":"/value","urlParsed":{"anchor":"","query":"","file":"value","directory":"/","path":"/value","relative":"/value","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/value","queryKey":{},"chunks":["value"]},"urlOriginal":"/session/ea0f7000-ab5c-11e6-acb9-5946ec8fdb06/element/:wdc:1479232631203/value"}} (WebDriver\Exception\InvalidElementState)
What I think is happening is that fillField() is trying to find the username field, but there are two, so for user1 the tests work but for user2, I get the error. I'd like some advice on how to handle this, besides changing the name of the un/pw fields.
Thanks
You need to have different selectors for each form. You can do this in few ways:
For the first 2 methods you will need to use another method to fill the elements and click the fields since you will use css selectors.
For example: find the element -> click() and find the element -> setValue()
1) create a method for each type with different selectors
loginWithUser1($username, $password){...}
loginWithUser2($username, $password){...}
loginWithUser3($username, $password){...}
You will need to use css selectors for the elements like:
#user1 input[name=username]
#user1 input[name=password]
2) use the same method and build/read selector from an array based on a parameter
login($username, $password, $role)
{
}
3) use page object functionality
This option will use a method same as the second one but instead of reading selectors from an array you will use a getElement() method and use the methods you need on that object. Please see here an example working with elements
I recommend to try the last option and if you can't make it work to try with the second one.
Tip: Avoid passing parameters in the method that you don't need like $btn from your login method.The method should know about the button element, you need to pass data only.

Element not visible, selenium

I am trying to login to a site.
This is the problematic html part:
<input name="pass" id="vic_login_password" autocomplete="off" class="inpHM3_2" dir="ltr" type="password" value="" id="PasswprdH1" /><input type="text" value="Password" onfocus="this.style.display='none'; gid('vic_login_password').style.display='block'; gid('vic_login_password').focus();" class="inpHM3_3" />
My code:
driver.findElementById("vic_login_password").SendKeys "fakepass"
I get an error no -2146233088 saying that element is not visible.
For the user name everything works fine this way, but for the password I always get this error.
The key to solve the problem is inside that onfocus() event handler:
onfocus="this.style.display='none'; gid('vic_login_password').style.display='block'; gid('vic_login_password').focus();"
It is actually making one input invisible and the other one visible. The other one is the input with id="vic_login_password" which is initially invisible. This explains the error you've got.
In your code, you should first focus the visible input and only then send keys to the other one:
driver.findElementByCssSelector("input[value=Password][onfocus]").Click
driver.findElementById("vic_login_password").SendKeys "fakepass"

TestStack.Seleno TickCheckbox not working

I have 2 forms that I am testing using TestStack.Seleno. Both forms have a checkbox that is mandatory. The first form has (including the checkbox) 5 fields. I can use TestStack.Seleno to create a passing test with valid data. I set the checkbox like this:
Input.TickCheckbox(f=>f.Accept,form.Accept);
On my other form which has 10 or so fields, when I try to set the checkbox to be ticked (using the same code) nothing happens. However when I try
var acceptCheckBox = Find.Element(By.Name("Accept"),new TimeSpan(0,0,0,50));
if (form.Accept)
{
acceptCheckBox.Click();
}
I get error "Element is not currently visible and so may not be interacted with"
Element is clearly visible and is not injected in using javascript.
I am using latest version of TestStack.Seleno from github.
Any ideas?
So I have managed to figure out what the issue is and have a work around, however I cannot explain why it works on the other form. The mandatory Accept field has html generated by mvc that looks like
<div>
<input class="check-box" data-val="true" data-val-mustbetrue="The Accept our field is required" data-val-required="The Accept our field is required." id="Accept" name="Accept" type="checkbox" value="true"><input name="Accept" type="hidden" value="false">
<label for="Accept">
Accept our Please accept our Terms and Conditions
</label>
<span class="field-validation-valid" data-valmsg-for="Accept" data-valmsg-replace="true"></span>
</div>
So you have the checkbox and hidden field both with id Accept, I suspect in code seleno is picking up the hidden field and setting value, so I updated my code todo
var acceptCheckBox = Find.Element(By.CssSelector("#Accept.check-box"));
acceptCheckBox.Click();
Now everything works.
Ismail

Cgi C program return value to main HTML and display result

I am programming a server side script on an Apache machine with cgi. I am using C for the cgi programming. I am a total noob and learning from online examples(I must say except the basics I didn't come across more web sources for detailed learning!).
I am having a simple HTML page where the username(input) is added to a list which is a file I have in my system and then the updated list should be displayed in the SAME PAGE.
I am not able to "print" the results of both the script and http link on the same page so therefore in the code below, you will only see buttons. Please help.
Here is what I have:
Html:
<html>
<head><title>Home</title></head>
<body>
<h1>REGISTER</h1>
<form action= "/cgi-bin/mycgi.cgi" name ="create user" method ="get">
Enter name:<input type="text" name="user">
<br>
<input type="submit" value="add">
</form>
<FORM action="http://localhost:8000/getusers/" method="get">
<P>
<input value="Display Users" type="submit">
</P>
</FORM>
</body>
Here is the cgi Code:
#include<stdio.h>
#include<string.h>
int main(){
char *tmpStr;
char *user;
printf("Content-Type:text/html\n\n");
printf("<html><head><title></title></head><body>");
tmpStr = getenv("QUERY_STRING");
while(tmpStr && *tmpStr != '='){
tmpStr++;
}
user = tmpStr+1,
printf("Adding %s to User Database",user);
//system("wget http://localhost:8000/newuser/");//call script to add user?
printf("</body></html>");
return 0;//return user?
}
Could you please tell me how I can realize these? How can I display the user list without opening a new html site? Also in the above C code, I have to call the link "http://localhost:8000/newuser/" which returns a success or failure value. How can I return it to the parent form?
Thanks.
You could add an iframe to your html:
<iframe id="theiframe" name="theiframe"></iframe>
And then setting the target of your form to the iframe:
<form action= "/cgi-bin/mycgi.cgi" name ="create user" method ="get" target="theiframe">
Anyway, it is not clear to me if the updated list should be displayed when you click on the first or second button.