Puppeteer.NET: Can't autopopulate field - c#

I am a just starting out with Puppeteer.NET, and i can't get it to autofill a login page.
The HTML for the web site looks like this:
<div class="main-wrapper">
<div class="row">
<div class="column section col-md-8">
<div class="loginForm">
<img src="images/logo.svg" width="300">
<br /><br /><br />
<div style="color: #454550; font-family: 'Neuzeit Grotesk'; font-size: 16px; ">
Welcome back
</div>
<br />
<form action="/login?app=LM&var=au" method="POST" name="login-form" id="login-form">
<input type="hidden" name="_csrf" value="BQ2YoR3d-5P__6b5HfqlVOjv8YgTypKV92XA" />
<div class="form-group text-center">
<input type="text" name="username" id="login-form-username" placeholder="Username" class="form-control" required value="">
</div>
<div class="form-group text-center">
<input type="password" name="password" id="login-form-password" placeholder="Password" class="form-control" required>
</div>
<div class="text-center">
<button type="submit" class="btn btn-danger btn-lg btn-block">Login</button>
</div>
</form>
<div style="color: #808083; margin-top: 30px; font-family: 'Roboto2';">
Trouble logging in?
<img src="images/grey_line.svg" width="300">
Sign up
</div>
</div>
<div style="text-align: center; width:400px;">
<img src="images/logo.svg" width="300">
</div>
</div>
<div class="column section col-md-4">
<iframe width="100%" height="100%" frameBorder="0" src="https://"></iframe>
</div>
</div>
</div>
I am trying to get it to fill in the login and password fields, and press the login button.
I am doing it as:
var extra = new PuppeteerExtra();
var stealth = new StealthPlugin();
LaunchOptions options = new LaunchOptions
{
Headless = false,
ExecutablePath = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"
};
Browser browser = extra.Use(stealth).LaunchAsync(options).Result;
string content = null;
using (Page page = browser.NewPageAsync().Result)
{
// do login screen
page.GoToAsync(url);
page.WaitForNavigationAsync();
page.WaitForSelectorAsync("username");
page.FocusAsync("username");
page.Keyboard.TypeAsync(login);
page.WaitForSelectorAsync("password");
page.FocusAsync("password");
page.Keyboard.TypeAsync(password);
page.ClickAsync("submit");
page.WaitForNavigationAsync();
content = page.GetContentAsync().Result;
}
I have tried changing the "username" to "#username" and some other variations, but nothing gets filled in. Ultimately, all I want to to login and then go to a specific page, and have a dump of the resultant HTML.
Also is there a easy way to just a text dump of the resultant HTML?

You can use the selectors #login-form-username and #login-form-password, those are the IDs.

Related

asp-validation-summary blocking back button

I have a page with a form doing validation on the model. The problem is its blocking the cancel button.
When the user clicks the cancel button its forcing them to supply a new password and confirm it. It should just send them back to the previous page.
#model Auth.Controllers.Account.RecoverPasswordViewModel
<div class="mdl-typography--text-center">
<h2 class="mdl-typography--headline">Gendan kodeord</h2>
<p class="mdl-typography--body-1">Gendand kodeord til din konto</p>
</div>
<div asp-validation-summary="ModelOnly" class="mdl-color-text--red-400"></div>
#using (Html.BeginForm("RecoverPassword", "Account", FormMethod.Post, new {#class = "form-horizontal", role = "form"})) {
<input type="hidden" asp-for="Code" />
<fieldset>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" asp-for="NewPassword" type="password" autocomplete="off" required autofocus/>
<label class="mdl-textfield__label" asp-for="NewPassword">Nyt kodeord</label>
<span asp-validation-for="NewPassword" class="mdl-textfield__error"></span>
</div>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" asp-for="ConfirmNewPassword" type="password" autocomplete="off" required/>
<label class="mdl-textfield__label" asp-for="ConfirmNewPassword">Bekræft nyt kodeord</label>
<span asp-validation-for="ConfirmNewPassword" class="mdl-textfield__error"></span>
<input type="hidden" asp-for="ReturnUrl" value="#Model.ReturnUrl" />
</div>
<div class="actions">
<button class="mdl-button mdl-button--primary" onclick="window.history.back()" causesvalidation="false">Gå tilbage</button>
<button class="mdl-button mdl-button--primary mdl-button--raised mdl-js-button mdl-js-ripple-effect">Gem</button>
</div>
</fieldset>
}
I tried adding causesvalidation="false" on the go back button but it didnt help. Is there a way to force it to only validate on the save button?
Don't use windows.history.back(), use redirect (RedirectToAction and the like).
windows.history.back() will trigger the previous request to be resent (if you came there from a post request) which is undesired behavior.
Instead create a link
<a class="mdl-button mdl-button--primary mdl-button--raised mdl-js-button mdl-js-ripple-effect"
asp-controller="MyController" asp-action="Index">Back</a>

pass textbox value as parameter to controller route

I'm trying to use a textbox value in controller route and am having some trouble with the syntax. Essentially, I have my end users selecting a file and then submitting the data to the api to process and send the data off. I have working static code below, but can't get the xml path to be dynamically populated via the textbox value.
note that (as far as I can tell) the forward slash at the end of the path is required since there is a dot in the file path.
#using (Html.BeginForm("", "api/food/dummy food file.xml/"))
{
<div class="row">
<div class="col-lg-6">
<label class="control-label">Select File</label>
<div class="input-group">
<label class="input-group-btn">
<span class="btn btn-default">
Browse… <input type="file" style="display: none;" single>
</span>
</label>
<input id="food.filepath" name="food.filepath" type="text" class="form-control" readonly>
</div>
</div>
</div>
<br />
<div>
<button id = "btnSubmit" type="submit" class="btn btn-primary">Submit</button>
</div>
}
I don't what the syntax would be, but I can't get something like the below to work.
#using (Html.BeginForm("", "api/food/" + food.filepath + "/"))
{
<div class="row">
<div class="col-lg-6">
<label class="control-label">Select File</label>
<div class="input-group">
<label class="input-group-btn">
<span class="btn btn-default">
Browse… <input type="file" style="display: none;" single>
</span>
</label>
<input id="food.filepath" name="food.filepath" type="text" class="form-control" readonly>
</div>
</div>
</div>
<br />
<div>
<button id = "btnSubmit" type="submit" class="btn btn-primary">Submit</button>
</div>
}
Because the form is rendered on server and the value food.filepath is on client, you cannot mix them. Changing form action according to client values need to be done on client with javascript.
You can remove the file from action a add it on submit javascript action, for example by changing BeginForm to this:
#using (Html.BeginForm("", "api/food/", FormMethod.Get, new { onSubmit = "this.dataset.act = this.dataset.act||this.action; this.action = this.dataset.act + this['food.filepath'].value" } ))

Selenium cant find element on element that exists in page

public class Sele
{
private IWebDriver driver;
private StringBuilder verificationErrors;
private string baseURL;
private bool acceptNextAlert = true;
public Sele( )
{
driver = new FirefoxDriver( );
baseURL = "https://www.youtube.com/";
verificationErrors = new StringBuilder( );
}
internal void LikeYoutubeVidWithAcc( string username, string password, string url )
{
driver.Navigate( ).GoToUrl( baseURL + "/" );
driver.FindElement( By.XPath( "(//button[#type='button'])[2]" ) ).Click( );
driver.FindElement( By.Id( "Email" ) ).Clear( );
driver.FindElement( By.Id( "Email" ) ).SendKeys( "UserName" );
driver.FindElement( By.Id( "next" ) ).Click( );
driver.FindElement( By.Id( "Passwd" ) ).Clear( );
driver.FindElement( By.Id( "Passwd" ) ).SendKeys( "Password" );
driver.FindElement( By.Id( "signIn" ) ).Click( );
driver.Navigate( ).GoToUrl( url );
driver.FindElement( By.XPath( "(//button[#type='button'])[25]" ) ).Click( );
}
}
I'm having trouble signing in to youtube using selenium, for some reason it can't find the password element in the page.
the error occurs at this line:
driver.FindElement( By.Id( "Passwd" ) ).Clear( );
Error message:
An unhandled exception of type 'OpenQA.Selenium.NoSuchElementException' occurred in WebDriver.dll
Additional information: Unable to locate element: {"method":"id","selector":"Passwd"}
I know the element exists on the page, yet selenium can't find it.
Page source when the error occurs:
<div class="card signin-card pre-shift no-name shift-form">
<div id="cc_iframe_parent"><iframe id="youtube" src="https://accounts.youtube.com/accounts/CheckConnection?pmpo=https%3A%2F%2Faccounts.google.com&v=-951713550&timestamp=1469398858532" style="visibility: hidden; width: 1px; height: 1px; position: absolute; top: -100px;"></iframe></div>
<div class="circle-mask" style="background-image: none;">
<canvas id="canvas" class="circle" width="96" height="96"></canvas>
</div>
<form novalidate="" method="post" action="https://accounts.google.com/signin/challenge/sl/password" id="gaia_loginform">
<input name="Page" value="PasswordSeparationSignIn" type="hidden">
<input name="GALX" value="bX35kb1ARtQ" type="hidden">
<input name="gxf" value="AFoagUWY2FAFLKhmD2_-vufme-BJ1jfACg:1469398858433" type="hidden">
<input name="continue" value="https://www.youtube.com/signin?next=%2F&hl=en&feature=sign_in_button&app=desktop&action_handle_signin=true" type="hidden">
<input name="service" value="youtube" type="hidden">
<input name="hl" value="en" type="hidden">
<input id="profile-information" name="ProfileInformation" value="APMTqulOYcx8i4BIKa7QX8vzLf8nHVle5wmAmPaLqZqa7bjp6poGeUD2zvzYvR46xap0wdwr2kQaxUuteML1f-hTwb_VW4ZDLaD0cYYzVup4THWBRGWMWv0" type="hidden">
<input id="_utf8" name="_utf8" value="☃" type="hidden">
<input name="bgresponse" id="bgresponse" value="!DwylDC1CEBfic73NLmFEPmLuo0jLmEwCAAAAH1IAAAAFCgASXF5p4wpYu2Whl5kDy5GtZSOFmQEOdst3NYj0yd4fKBLZxl94_2g92h7yeFimnFaHcZosa1A6tveg3lkaz-HEnxsgWWDRAptp3hXbMHf10f_l5URE4mup4YdMKniavQDRHw1mYbNpaTFcVbTQhb2Fq8zAY89pRskujAVj_FVIMin3uw8U3Ncz0sjSkkSBbSi7TneLgUGXSI-GHNUS6uVJGKfqXUCSMkdDA2d71bq-oANdlKwxKOyCAAIkcNAwwuROjGY1wiWaMRofROyHO3PfRvpdwtKP0MfCUCvFU88cdyXKHt-xyJO76CR96U3E5loZGOFscMs8BCy2KpyjeyE6yGHVcSAMFI9NgQfT0Gv5E4687eD__44iyMRuyd4xUYcetZAL" type="hidden">
<input id="pstMsg" name="pstMsg" value="1" type="hidden">
<input id="dnConn" name="dnConn" value="" type="hidden">
<input id="checkConnection" name="checkConnection" value="youtube:254:1" type="hidden">
<input id="checkedDomains" name="checkedDomains" value="youtube" type="hidden">
<div class="form-panel first valid" id="gaia_firstform">
<div style="transition-delay: 0ms;" class="slide-out hide-form">
<div class="input-wrapper focused">
<div id="identifier-shown"></div>
<span role="alert" class="error-msg" id="errormsg_0_Email"></span>
</div>
<div style="display: none" id="identifier-captcha">
<input name="identifiertoken" id="identifier-token" value="" type="hidden">
<input name="identifiertoken_audio" id="identifier-token-audio" type="hidden">
<div class="audio-box">
<div id="playIdentifierAudio"></div>
</div>
<div id="captcha-box" class="captcha-box">
<div id="captcha-img" class="captcha-img" data-alt-text="Visual verification"></div>
<span class="captcha-msg">
Letters are not case-sensitive
</span>
</div>
<label for="identifier-captcha-input" class="hidden-label"></label>
<input id="identifier-captcha-input" name="identifier-captcha-input" class="captcha" placeholder="Enter the letters above" title="Type the characters you see or numbers you hear" type="text">
</div>
<input id="next" name="signIn" class="rc-button rc-button-submit" value="Next" type="submit">
<a class="need-help" href="https://accounts.google.com/signin/recovery?continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Fnext%3D%252F%26hl%3Den%26feature%3Dsign_in_button%26app%3Ddesktop%26action_handle_signin%3Dtrue&service=youtube&ignoreShadow=0&hl=en">
Need help?
</a>
</div>
</div>
<a href="https://accounts.google.com/ServiceLogin?continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Fnext%3D%252F%26hl%3Den%26feature%3Dsign_in_button%26app%3Ddesktop%26action_handle_signin%3Dtrue&service=youtube&hl=en" tabindex="-1">
<img id="back-arrow" class="back-arrow shift-form" aria-label="Back" tabindex="0" alt="Back" src="https://www.gstatic.com/images/icons/material/system/1x/arrow_back_grey600_24dp.png">
</a>
<div class="form-panel second">
<div style="transition-delay: 100ms;" class="slide-in">
<div>
<p style="display: none;" id="profile-name"></p>
<span id="email-display">email123456#gmail.com</span>
</div>
<div>
<div id="password-shown"><div>
<input name="Email" id="Email-hidden" spellcheck="false" class="hidden" value="" readonly="" autocomplete="off" type="email">
<label class="hidden-label" for="Passwd">Password</label>
<input id="Passwd" name="Passwd" placeholder="Password" class="" type="password">
</div></div>
</div>
<input id="signIn" name="signIn" class="rc-button rc-button-submit" value="Sign in" type="submit">
<label class="remember">
<input id="PersistentCookie" name="PersistentCookie" value="yes" checked="checked" type="checkbox">
<span>
Stay signed in
</span>
<div class="bubble-wrap" role="tooltip">
<div class="bubble-pointer"></div>
<div class="bubble">
For your convenience, keep this checked. On shared devices, additional precautions are recommended.
Learn more
</div>
</div>
</label>
<input name="rmShown" value="1" type="hidden">
<a id="link-forgot-passwd" class="need-help" href="https://accounts.google.com/signin/recovery?continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Fnext%3D%252F%26hl%3Den%26feature%3Dsign_in_button%26app%3Ddesktop%26action_handle_signin%3Dtrue&service=youtube&checkedDomains=youtube&checkConnection=youtube%3A254%3A1&pstMsg=1&Email=wageeh14032%40gmail.com&ignoreShadow=0&hl=en">
Forgot password?
</a>
</div>
</div>
<span id="inge" style="display: none" role="alert" class="error-msg">
Sorry, Google doesn't recognize that email. Create an account using that address?
</span>
<span id="timeoutError" style="display: none" role="alert" class="error-msg">
Something went wrong. Check your connection and try again.
</span>
</form>
</div>
Try this:
WebDriverWait wait = new WebDriverWait(driver, 10); //you can change 10 seconds to whatever it suits you the best.
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("Passwd")));

form data passing issue with MVC and Razor

I'm using razor html and attempting to post data to a function. I can get parts of the data to submit and go across just fine but other parts i can not.
#using (Html.BeginForm("Reply", "api/Reply", new { ID = Model.ID, UserName = Model.Username }))
{
<div id="mainArea" class="lightboxContent" style="display: block">
<div class="lightboxText">
<div class="responderTitleLeft">Select Profile: </div>
<div class="responderFormFloat">
<select name="profileSelector" class="select-style">
<option value="Select One" selected>Please Select Your Profile</option>
#foreach (var profile in Model.ProfileModels)
{
<option value="#profile.ProfileID">#profile.ScreenName</option>
}
</select>
</div>
<div class="responderActions">
<div id="Reply" class="TwtiterReply">
<a href="javascript:void(0)">
<img src="/images/engage/actions/reply.png" onclick="toggle('ReplyArea')" title="Reply to message" />
</a>
</div>
<div id="ReplyArea" style="display: none;" class="responderForm">
<div class="responderTitle">Reply</div>
<textarea id="MessageEdit" name="Message" onkeyup="return characterCount(this)" onchange="postChange(this.id, 'messagePreview');" rows="4" cols="50" style="resize: none">#Model.Username</textarea>
<p id="counter"><strong><span id="charCount">140</span></strong> more characters available.</p>
<div class="lightboxButtonsBar">
<input type="button" onclick="toggle('mainArea')" tabindex="3" value="Reply" />
<input type="button" class="cancel" tabindex="4" value="Cancel" />
</div>
</div>
</div>
</div>
</div>
<div id="confirmArea" class="confirmationArea" style="display: none">
<div class="warning">
<p><strong>Warning:</strong></p>
</div>
<div class="warningMessage">
<p>You are posting from #Model.ProfileModels with the message:</p>
<div class="messagePreviewArea" data-form="Reply">
<p>
<textarea id="messagePreview" readonly rows="4" cols="50" style="color: #ffffff; font-size: .9em; background-color: transparent; resize: none; border-color: #808080;"></textarea></p>
<input type="submit" tabindex="3" value="Confirm" />
<input type="button" onclick="toggle('mainArea')" tabindex="3" value="Cancel" />
</div>
</div>
</div>
}
public UserProfile Reply(string ID, string UserName, FormCollection form)
{
var pSelector = form["profileSelector"];
var message = form["Message"];
ApiService msgserv = new ApiService();
UserProfile up = UserProfile.GetFirst(new Guid(pSelector));
messenger.Reply(up.key, UserName, ID, message);
return up;
}
what i'm looking to get out of this form (in order of how it's show) ID, and username (they are provided by the model and i get those no problem.)
The ones i'm having issues with is the profile selector and the text area with the name message.
Can someone point me in the right direction on how to get a textarea and a select into a form?
The reason the select is not providing the model with data is because its name property is not set to corresponing property name in the model. The same goes for the text area. Generally speaking, if you want the form submit to fill those property you use the 'strongly-typed' helper methods, such as DropdownFor and CheckBoxFor. Or you can manually wire those up, try setting the name of the select element to "SelectedProfile" and changing the Reply action to: Reply(string ID,string Username,string SelectedProfile, FormCollection form)
To get from the textarea do something like this on your view #Html.TextArea("messagePreview"); But I would recommend saving things in your model if you can.

Html.OpenIdSelector in mvc3

I have the buttons rendering and here is the output:
<form action="/Auth/LogOnPostAssertion" method="post" target="_top">
<input name="__RequestVerificationToken" type="hidden" value="M+ZFyksulpHW8asKultS/Y53gRs6eEli13rjL76+tc40ZB4WUbxAIpVMtsMnyGI2hXZ54DwyFypx/0UBlZqR+U7F/ALJRHiIGU9dCJpiohZHrlVEYZMgsF9HB14wruRia5A7jOidi4DlyfRriMjGrn63RMMJlLLHWIq5duSUiR4=" /><input
id="ReturnUrl" name="ReturnUrl" type="hidden" value="" /><input id="openid_openidAuthData"
name="openid_openidAuthData" type="hidden" value="" />
<div id="login-oauth-container">
<ul class="OpenIdProviders">
<li id="https://me.yahoo.com/" class="OPButton"><a href="#">
<div>
<div>
<img src="/Content/images/yahoo.gif" /><img src="http://www.google.com/" class="loginSuccess"
title="Authenticated as {0}" />
</div>
<div class="ui-widget-overlay">
</div>
</div>
</a></li>
<li id="https://www.google.com/accounts/o8/id" class="OPButton"><a href="#">
<div>
<div>
<img src="/Content/images/google.gif" /><img src="http://www.google.com/" class="loginSuccess"
title="Authenticated as {0}" />
</div>
<div class="ui-widget-overlay">
</div>
</div>
</a></li>
<li id="OpenIDButton" class="OpenIDButton"><a href="#">
<div>
<div>
<img src="/Content/images/openid.gif" /><img src="http://www.google.com/" class="loginSuccess"
title="Authenticated as {0}" />
</div>
<div class="ui-widget-overlay">
</div>
</div>
</a></li>
</ul>
<div style='display: none' id='OpenIDForm'>
<span class='OpenIdAjaxTextBox' style='display: inline-block; position: relative;
font-size: 16px'>
<input name='openid_identifier' id='openid_identifier' size='40' style='padding-left: 18px;
border-style: solid; border-width: 1px; border-color: lightgray' />
</span>
</div>
<div class="helpDoc">
<p>
If you have logged in previously, click the same button you did last time.
</p>
</div>
</div>
</form>
it has the webresource css too.
However, clicking on the buttons does nothing. on the nerddinner sample it obv pops up the login box for the provider you select.
what do i need to do to make this work? is there a checklist of things i need to be aware of?

Categories