Selenium ChromeDriver authentication (with C#) - selenium

I've been trying to automate a simple process for two days now. I started with a web scraper (as I'd just finished a project using that), but quickly found this wasn't a good option. The site I need access to runs some scripts when the form posts, and I can't get it to work with the scraper. So I turned to HttpWebRequest and HttpWebResponse. Whole lot of banging my head against the wall, no dice. So I tried the Selenium ChromeDriver, and so far that's the closest I've come to getting this to work. I need to:
Load login page and submit login form (can't send in URL - doesn't work).
Load report form page.
Change field values.
Submit report form.
Download CSV response.
Here's my current code:
var username = _configuration.GetValue<string>("LoginCreds:username");
var password = _configuration.GetValue<string>("LoginCreds:password");
var driver = new ChromeDriver(#"C:\Users\path\to\libs");
driver.Url = "https://mydomain.loginpage.com";
driver.Navigate();
var usernameField = driver.FindElementById("username");
usernameField.SendKeys(username);
var passwordField = driver.FindElementById("password");
passwordField.SendKeys(password);
driver.FindElementById("submit").Submit();
// Handle browser version alert.
var alert = driver.SwitchTo().Alert();
alert.Dismiss();
var html = driver.PageSource;
Console.WriteLine(html); // This is the HTML of the authenticated page - as expected.
Console.ReadKey();
// Load report form page.
driver.Navigate().GoToUrl("https://mydomain.reports.com");
html = driver.PageSource;
Console.WriteLine(html); // Now I get the login page HTML - authentication is lost.
Console.ReadKey();
So authentication seems to be working, but it doesn't persist. I need to be able to move about on the site after authenticating.

It's working now with the code I posted. Turned out I had multiple windows open, authenticated to that site, so even refreshing the page was posting back to the login page. Turns out that the ChromeDriver did the trick just fine. I was even able to download the CSV file I need, which is dynamically generated, so there isn't a static URL I can map to for downloading. Here's the working code:
var username = _configuration.GetValue<string>("LoginCreds:username");
var password = _configuration.GetValue<string>("LoginCreds:password");
var chromeOptions = new ChromeOptions();
chromeOptions.AddUserProfilePreference("download.default_directory", #"C:\Users\path\to\download\WorkingDirectory");
chromeOptions.AddUserProfilePreference("diable-popup-blocking", "true");
var driver = new ChromeDriver(#"C:\Users\path\to\libs", chromeOptions);
driver.Url = "https://mydomain.loginpage.com";
driver.Navigate();
driver.FindElementById("username").SendKeys(username);
driver.FindElementById("password").SendKeys(password);
driver.FindElementById("submit").Submit();
// Handle browser version alert.
driver.SwitchTo().Alert().Dismiss();
// Load report form page.
driver.Navigate().GoToUrl("https://mydomain.reports.com");
driver.FindElementByName("Option1").Click();
driver.FindElementByName("Option2").Click();
driver.FindElementByName("Option3").Click();
driver.FindElementById("submit").Submit();
Thread.Sleep(30000);
driver.Close();
driver.Quit();
I wasn't able to find an elegant solution to close the browser and the console when the download completes. There are solutions posted that scan the download director for a completed file, but that was a lot of effort for little yield. Waiting for 30 seconds gives the CSV file plenty of time to download, and the browser/console cleanup isn't time-sensitive.

Related

How to send filesteam to browser in blazor app

I need to call a web api that returns a pdf. I want to display that pdf when the user clicks a download button. Here's my code. Nothing seems to happen when the button is clicked although through debug I can see the successful download of the file from the api and writing to local disk. I'd prefer to send the file straight to the browser instead of downloading. Here is what I've tried.
On the page
button #onclick="#(e => Download_doc())">Download
In my .cs
var request = new HttpRequestMessage(HttpMethod.Get, "URL");
HttpResponseMessage resp = await client.SendAsync(request);
var file = System.IO.File.Create("download.pdf");
var content = await resp.Content.ReadAsStreamAsync();
await content.CopyToAsync(file);
Console.Write(file);
return file;
Any suggestions would be appreciated.

Task Module call from Ms Teams in Bot Framework

I am looking to open a task module (Pop up - iframe with audio/video) in my bot that is connected to Teams channel. I am having issues following the sample code provided on the GitHub page.
I have tried to follow the sample and incorporate to my code by did not succeed.
In my bot.cs file I am creating card action of invoke type:
card.Buttons.Add(new CardAction("invoke", TaskModuleUIConstants.YouTube.ButtonTitle, null,null,null,
new Teams.Samples.TaskModule.Web.Models.BotFrameworkCardValue<string>()
{
Data = TaskModuleUIConstants.YouTube.Id
}));
In my BotController.cs that inherits from Controller
[HttpPost]
public async Task PostAsync()
{
// Delegate the processing of the HTTP POST to the adapter.
// The adapter will invoke the bot.
await _adapter.ProcessAsync(Request, Response, _bot);
}
public async Task<HttpResponseMessage> Post([FromBody] Activity activity)
{
if (activity.Type == ActivityTypes.Invoke)
{
return HandleInvokeMessages(activity);
}
return new HttpResponseMessage(HttpStatusCode.Accepted);
}
private HttpResponseMessage HandleInvokeMessages (Activity activity)
{
var activityValue = activity.Value.ToString();
if (activity.Name == "task/fetch")
{
var action = Newtonsoft.Json.JsonConvert.DeserializeObject<Teams.Samples.TaskModule.Web.Models.BotFrameworkCardValue<string>>(activityValue);
Teams.Samples.TaskModule.Web.Models.TaskInfo taskInfo = GetTaskInfo(action.Data);
Teams.Samples.TaskModule.Web.Models.TaskEnvelope taskEnvelope = new Teams.Samples.TaskModule.Web.Models.TaskEnvelope
{
Task = new Teams.Samples.TaskModule.Web.Models.Task()
{
Type = Teams.Samples.TaskModule.Web.Models.TaskType.Continue,
TaskInfo = taskInfo
}
};
return msg;
}
return new HttpResponseMessage(HttpStatusCode.Accepted);
}
There is more code as per the GitHub sample but I won't paste it here. Can someone point me into the correct direction ?
I have got to the stage that it is displaying a pop up window but the content and title comes from manifest file instead of creating actual iframe also no video is rendering. My goal is to render video within my teams using iframe container.
The important part from the sample:
This sample is deployed on Microsoft Azure and you can try it yourself by uploading Task Module CSharp.zip to one of your teams and/or as a personal app. (Sideloading must be enabled for your tenant; see step 6 here.) The app is running on the free Azure tier, so it may take a while to load if you haven't used it recently and it goes back to sleep quickly if it's not being used, but once it's loaded it's pretty snappy.
So,
Your Teams Admin MUST enable sideloading
Your bot MUST be sideloaded into Teams
The easiest way to do this would be download the sample manifest, open it in App Studio, then edit your bot information in. You then need to make sure Domains and permissions > Valid Domains are set for your bot. Also ensure you change the Tabs URLs to your own.
You also need to make sure that in your Tasks, the URLs they call ALL use https and not http. If anywhere in the chain is using http (like if you're using ngrok and http://localhost), it won't work.

jMeter - Selenium integration

I have jMeter test case already written, it has requests for logging in and some POST requests to my table.
Now I want to measure render time of the page (response of the POSTS).
I want to use Selenium so I read:
Running Selenium scripts with JMeter
The problem is that i want Selenium to use the same session (in other words: to be already logged in) as logging in was handled by jMeter already.
How can i archive that ?
My TestPlan:
[UPDATE]
#Dmitri T
Thanks for answer! I did what you have suggested but it still don't work. Maybe I am doing something wrong but still just after Selenium opens browser it goes to login page. I put JSR223 PostProcessor under my LOGIN POST request and this is my WebDriver Sampler:
var pkg = JavaImporter(org.openqa.selenium);
var support_ui = JavaImporter(org.openqa.selenium.support.ui.WebDriverWait);
var wait = new support_ui.WebDriverWait(WDS.browser, 5000);
WDS.sampleResult.sampleStart();
WDS.sampleResult.getLatency();
WDS.log.info("Sample started");
WDS.browser.get(WDS.parameters);
WDS.log.info("LOGGING INTO: " + (WDS.parameters))
var cookieManager = WDS.vars.getObject('cookieManager')
for (var i=0; i < cookieManager.getCookieCount(); i++) {
var jmeterCookie = cookieManager.getCookies().get(i)
var seleniumCookie = new org.openqa.selenium.Cookie(jmeterCookie.name, jmeterCookie.value, jmeterCookie.domain, jmeterCookie.path, java.util.Date.from(java. time.Instant.ofEpochMilli(jmeterCookie.expiresMillis)), jmeterCookie.secure)
WDS.browser.manage().addCookie(seleniumCookie)
}
java.lang.Thread.sleep(5000)
WDS.sampleResult.sampleEnd();
{UPDATE 2}
Ok, i think that htere is something wrong with Cookies in all Thread Group.
I have [no cookies] on every request:
In order to pass the "session" you need to copy all the cookies from JMeter's HTTP Cookie Manager into the Selenium session.
This can be done in the WebDriver Sampler directly as follows:
Add JSR223 PostProcessor as a child of the request which session you want to copy
Put the following code into "Script" area
vars.putObject('cookieManager', sampler.getCookieManager())
it will store the current state of the HTTP Cookie Manager into JMeter Variables
In the WebDriver Sampler you can copy the cookies from the HTTP Cookie Manager and add them to the WebDriver instance using WDS.browser.manage().addCookie() function as follows:
var cookieManager = WDS.vars.getObject('cookieManager')
for (var i=0; i < cookieManager.getCookieCount(); i++) {
var jmeterCookie = cookieManager.getCookies().get(i)
var seleniumCookie = new org.openqa.selenium.Cookie(jmeterCookie.name, jmeterCookie.value, jmeterCookie.domain, jmeterCookie.path, java.util.Date.from(java.time.Instant.ofEpochMilli(jmeterCookie.expiresMillis)), jmeterCookie.secure)
WDS.browser.manage().addCookie(seleniumCookie)
}

C# Oauth2 retrieve Auth Code

I have been working on the process of Oauth2. I am writing a C# win form application. I am trying to figure out if there is a way to do a http request to get the Authorization code instead of a web browser pops up and asks for "Grant Access". If it has to do so, i am wondering how i can pass that code to the program? I am not sure how i get pass that to the console since i am using a C# form app.
public static IAuthorizationState getState(NativeApplicationClient arg)
{
IAuthorizationState state = new AuthorizationState(new[] {AnalyticsService.Scopes.Analytics.GetStringValue()});
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
Uri authUri = arg.RequestUserAuthorization(state);
Process.Start(authUri.ToString());
Console.Write(" Authorization Code: ");
string authCode = Console.ReadLine();
Console.WriteLine();
return arg.ProcessUserAuthorization(authCode, state);
}
You can call a browser control from your app. Once your user successfully logs in to Google and authorizes your app from that browser control, parse the authorization code from the title of the page your browser control is left on.
See here:
https://developers.google.com/youtube/2.0/developers_guide_protocol_oauth2#OAuth2_Installed_Applications_Flow
If you set the redirect_uri to urn:ietf:wg:oauth:2.0:oob, Google's authorization server will return a page to the browser like the one shown below. Your application can then extract the authorization code from the page title.
Be careful to parse the code exactly how they describe to. Then proceed to close the browser control and do what you need to do.

RavenDB in embedded mode - Raven Silverlight Studio (Raven.Studio.xap) not working

I have a small console application doing some persistence with Raven which is working fine, but I just can't get the Raven Studio Web-App working.
I think I have read every article/blog post on the web which is around, but I haven't got it working.
The project is referencing the Raven.Client.Embedded, Raven.Client.Lightweight and Raven.Storage.Esent assemblies)
Here is the really simple code starting up my console app:
class Program
{
static void Main(string[] args)
{
EmbeddableDocumentStore store = new EmbeddableDocumentStore { DataDirectory = #"C:\temp\ravendata", UseEmbeddedHttpServer = true };
store.Initialize();
Console.WriteLine("Initialized");
while (true)
{
string line = Console.ReadLine();
if (line == "w")
{
Changeset cs = CreateChangeset();
using (var session = store.OpenSession())
{
session.Store(cs);
session.SaveChanges();
}
Console.WriteLine("Written.");
}
}
The question is: Where to put the Raven.Studio.xap in order to get it running in the browser (http://localhost:8080/Raven/studio.html)?
It's not working in the bin/debug output folder of my console app (which would be the most logical area where it should be), as well as it isn't if I put it in the root of my console application.
Sorry to ask this thing again, but it seems there is some point I am missing on this to get it up and running. ;)
Thanks for your help, R's, Rene
You are right, I've tried it using a new console application project and had the same issues, altough I copied the file Raven.Studio.xap into the \bin\debug AFTER I had seen the error message for the first time.
I found out, that the reason for this has to do with browser-caching. Even though the file would be available now, the embedded http-server returns 304 Not Modified, because it had sent the If-None-Match header into the request. Therefore, the cached "not-found" page in the browser cache will be used.
I fixed it and sent a patch to Ayende. However the solution now is:
1) make sure Raven.Studio.xap is under \bin\debug
2) clear the browsers cache