How to handle wrong credentials during authentication with C# (Selenium) used? - selenium

I learn myself of writing Selenium C# automated tests. Now I try to go to the authentication page and send WRONG credentials, submit and check "Not Authorised" text on page. Seems to be simply, but the problem is that when I send credentials to the driver, authentication popup appears, but no user and password input. After all I get the message that OpenQA.Selenium.NoAlertPresentException : no such alert. Is there any simple way in C# to resolve this?
Here is my code:
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.DevTools;
using OpenQA.Selenium.Support.UI;
namespace Selenium2.Authorisation
{
public class Authorisation
{
IWebDriver driver;
[SetUp]
public void Setup()
{
driver = new ChromeDriver();
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
driver.Manage().Window.Maximize();
}
[Test]
public void SendWrongUsernameToAuthenticationPopupTest()
{
String username = "abc";
String password = "admin";
String URL = "https://" + username + ":" + password + "#" + "the-internet.herokuapp.com/basic_auth";
driver.Navigate().GoToUrl(URL);
//tried this but received error: OpenQA.Selenium.NoAlertPresentException : no such alert
IAlert alert = driver.SwitchTo().Alert();
alert.SendKeys(username);
alert.Accept();
driver.Manage().Timeouts().Equals(TimeSpan.FromSeconds(5));
String text = driver.FindElement(By.TagName("p")).Text;
String expectedText = "Not authorized";
IWebElement p2 = driver.FindElement(By.TagName("body"));
Assert.AreEqual(expectedText, p2.Text, "The unauthorised texts are not the same");
}

Through Basic Authentication the user does gets logged in. You don't require to authenticate the user anymore unless explicitly asked to login.
[Test]
public void SendWrongUsernameToAuthenticationPopupTest()
{
String username = "abc";
String password = "admin";
String URL = "https://" + username + ":" + password + "#" + "the-internet.herokuapp.com/basic_auth";
driver.Navigate().GoToUrl(URL);
driver.Manage().Timeouts().Equals(TimeSpan.FromSeconds(5));
String text = driver.FindElement(By.TagName("p")).Text;
String expectedText = "Not authorized";
IWebElement p2 = driver.FindElement(By.TagName("body"));
Assert.AreEqual(expectedText, p2.Text, "The unauthorised texts are not the same");
}

Related

Selenium: cookie functionality not working

I am new to selenium. I am trying to test an application. Application has two pages login.jsp, restricted.jsp. You can access restricted.jsp, only after login (trying to access restricted.jsp without login will redirect to login.jsp page). My selenium application is like below.
a. Login to the app first
b. After successful login, store all the cookies to "session.properties" file.
c. Next time onwards, I am loading all the cookies from "session.properties" to driver and try to access "restricted.jsp" page. But I am redirecting to login.jsp, instead of restricted.jsp.
Following is my Java code.
public class App {
private static void loginApp(WebDriver driver) {
driver.get("http://localhost:8080/selenium_app/login");
WebElement userName = driver.findElement(By.name("userName"));
WebElement password = driver.findElement(By.name("password"));
userName.sendKeys("admin");
password.sendKeys("admin");
userName.submit();
}
private static void storeSessionProps(WebDriver driver) throws IOException {
File f = new File("session.properties");
f.delete();
f.createNewFile();
FileWriter fos = new FileWriter(f);
BufferedWriter bos = new BufferedWriter(fos);
/* Get all the cookies and store them to session.properties file */
Set<Cookie> cookies = driver.manage().getCookies();
for (Cookie cookie : cookies) {
bos.write(cookie.getName() + "=" + cookie.getValue());
bos.newLine();
}
bos.flush();
bos.close();
fos.close();
}
private static void loadPropertiesToDriver(WebDriver driver)
throws IOException {
Properties properties = new Properties();
FileInputStream fin = new FileInputStream("session.properties");
properties.load(fin);
Set<Object> props = properties.keySet();
for (Object prop : props) {
Cookie ck = new Cookie((String) prop,
properties.getProperty((String) prop));
driver.manage().addCookie(ck);
System.out.println(ck);
}
}
public static void main(String[] args) throws InterruptedException,
IOException {
WebDriver driver = new FirefoxDriver();
// loginApp(driver);
// storeSessionProps(driver);
loadPropertiesToDriver(driver);
driver.get("http://localhost:8080/selenium_app/restricted");
Thread.sleep(5000);
driver.quit();
}
}
When I uncomment the lines loginApp(driver);, storeSessionProps(driver); everything is fine, I am able to access restricted.jsp page, but when I ran application by commenting those and loading the cookies, I am redirecting to login.jsp page. Any help on this??
You need to store all the data from your cookies, not just the names/values. Moreover, before creating a cookie, your need to load a page with a domain that will match the domain of the cookie.
This is an example to quickly store and restore the cookies:
Path cookiesFile = Paths.get("C:\\Temp\\cookies.txt");
WebDriver driver = new FirefoxDriver();
JavascriptExecutor js = (JavascriptExecutor)driver;
// load the domain
driver.get("https://www.google.com");
if(cookiesFile.toFile().exists()) {
// load the cookies into the browser for the current domain
String cookies = new String(Files.readAllBytes(cookiesFile), Charsets.UTF_8);
js.executeScript(cookies);
// reload the page with the injected cookies
driver.get("https://www.google.com");
}
// save the cookies to a file for the current domain
try(PrintWriter file = new PrintWriter(cookiesFile.toFile(), "UTF-8")){
for(Cookie c : driver.manage().getCookies()) {
file.println("document.cookie='" + c.toString() + "';");
}
}

Rally: How to Map test cases with user stories using REST API?

I am writing code to create new test cases using rally restAPI.
Able to create the test cases under Test Plan & Test folder.
Now, want to map those test cases to Rally user stories.
Work product is the field to map it. But how to get the reference of user story using restAPI?
Please let me know if anyone has done in past.
In WS API user story is HierarchicalRequirement object. Query on the story, which you want to be a workproduct, and get its _ref. Then update the test case, e.g.
testCaseUpdate.addProperty("WorkProduct", storyRef);
Here is a Java example using Rally Rest toolkit for Java, but the approach is the same regardless of your choice of language or toolkit:
public class UpdateTestCase {
public static void main(String[] args) throws URISyntaxException, IOException {
String host = "https://rally1.rallydev.com";
String apiKey = "_abc123";
String workspaceRef = "/workspace/123456";
String applicationName = "RestExample_updateWorkProductOnTestCase";
RallyRestApi restApi = new RallyRestApi(new URI(host),apiKey);
restApi.setApplicationName(applicationName);
try {
String testid = "TC12";
String storyid = "US34";
QueryRequest testCaseRequest = new QueryRequest("TestCase");
testCaseRequest.setWorkspace(workspaceRef);
testCaseRequest.setFetch(new Fetch("FormattedID", "Name", "WorkProduct"));
testCaseRequest.setQueryFilter(new QueryFilter("FormattedID", "=", testid));
QueryResponse testCaseQueryResponse = restApi.query(testCaseRequest);;
if (testCaseQueryResponse.getTotalResultCount() == 0) {
System.out.println("Cannot find test case : " + testid);
return;
}
JsonObject testCaseJsonObject = testCaseQueryResponse.getResults().get(0).getAsJsonObject();
String testCaseRef = testCaseJsonObject.get("_ref").getAsString();
System.out.println(testCaseRef);
QueryRequest storyRequest = new QueryRequest("HierarchicalRequirement");
storyRequest.setWorkspace(workspaceRef);
storyRequest.setFetch(new Fetch("FormattedID", "Name"));
storyRequest.setQueryFilter(new QueryFilter("FormattedID", "=", storyid));
QueryResponse storyQueryResponse = restApi.query(storyRequest);;
if (storyQueryResponse.getTotalResultCount() == 0) {
System.out.println("Cannot find test story : " + storyid);
return;
}
JsonObject storyJsonObject = storyQueryResponse.getResults().get(0).getAsJsonObject();
String storyRef = storyJsonObject.get("_ref").getAsString();
System.out.println(storyRef);
JsonObject testCaseUpdate = new JsonObject();
testCaseUpdate.addProperty("WorkProduct", storyRef);
UpdateRequest updateTestCaseRequest = new UpdateRequest(testCaseRef,testCaseUpdate);
UpdateResponse updateTestCaseResponse = restApi.update(updateTestCaseRequest);
if (updateTestCaseResponse.wasSuccessful()) {
System.out.println("Successfully updated : " + testid + " WorkProduct after update: " + testCaseUpdate.get("WorkProduct"));
}
} finally {
restApi.close();
}
}
}

MvvmCross HTTP DownloadCache with authentication

In my app, the user need to be authenticated on the server to download data using WebAPIs.
The MvvmCross DownloadCache plugin seems to handle only basic HTTP GET queries. I can't add my authentication token in the url as it's a big SAML token.
How can I add a HTTP header to queries done through DownloadCache plugin ?
With the current version I think I should inject my own IMvxHttpFileDownloader but I'm looking for an easier solution. Injecting my own MvxFileDownloadRequest would be better (not perfect) but it doesn't have an interface...
I'm able to do it registering a custom IWebRequestCreate for a custom scheme (http-auth://).
It's a bit ugly to transform urls from my datasource but it does the job.
public class AuthenticationWebRequestCreate : IWebRequestCreate
{
public const string HttpPrefix = "http-auth";
public const string HttpsPrefix = "https-auth";
private static string EncodeCredential(string userName, string password)
{
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
string credential = userName + ":" + password;
return Convert.ToBase64String(encoding.GetBytes(credential));
}
public static void RegisterBasicAuthentication(string userName, string password)
{
var authenticateValue = "Basic " + EncodeCredential(userName, password);
AuthenticationWebRequestCreate requestCreate = new AuthenticationWebRequestCreate(authenticateValue);
Register(requestCreate);
}
public static void RegisterSamlAuthentication(string token)
{
var authenticateValue = "SAML2 " + token;
AuthenticationWebRequestCreate requestCreate = new AuthenticationWebRequestCreate(authenticateValue);
Register(requestCreate);
}
private static void Register(AuthenticationWebRequestCreate authenticationWebRequestCreate)
{
WebRequest.RegisterPrefix(HttpPrefix, authenticationWebRequestCreate);
WebRequest.RegisterPrefix(HttpsPrefix, authenticationWebRequestCreate);
}
private readonly string _authenticateValue;
public AuthenticationWebRequestCreate(string authenticateValue)
{
_authenticateValue = authenticateValue;
}
public WebRequest Create(System.Uri uri)
{
UriBuilder uriBuilder = new UriBuilder(uri);
switch (uriBuilder.Scheme)
{
case HttpPrefix:
uriBuilder.Scheme = "http";
break;
case HttpsPrefix:
uriBuilder.Scheme = "https";
break;
default:
break;
}
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uriBuilder.Uri);
request.Headers[HttpRequestHeader.Authorization] = _authenticateValue;
return request;
}
}

How to create HMACSHA256 api signature in Salesforce Apex

Can somebody help in creating HMACSHA256 api signature in apex using crypto class. Corresponding java code is given below :-
public static void main(String[] args) throws GeneralSecurityException, IOException {
String secretKey = "secretKey";
String salt = "0123456789";
String generateHmacSHA256Signature = generateHmacSHA256Signature(salt, secretKey);
System.out.println("Signature: " + generateHmacSHA256Signature);
String urlEncodedSign = URLEncoder.encode(generateHmacSHA256Signature, "UTF-8");
System.out.println("Url encoded value: " + urlEncodedSign);
}
public static String generateHmacSHA256Signature(String data, String key) throws GeneralSecurityException {
byte[] hmacData = null;
try {
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKey);
hmacData = mac.doFinal(data.getBytes("UTF-8"));
return new Base64Encoder().encode(hmacData);
} catch (UnsupportedEncodingException e) {
throw new GeneralSecurityException(e);
}
}
Thanks in advance
http://boards.developerforce.com/t5/Apex-Code-Development/How-to-create-HMACSHA256-api-signature/td-p/551055
I think that'll do it for you?
Copied here for posterity (in case the link dies)
AKK's answer:
"Re: How to create HMACSHA256 api signature
‎12-28-2012 02:58 AM
Sorry for unformatted code, actually I was looking into how to format but didn't find anything in mozilla and when login through chrome editor appeared.
I got the signature right using below code maybe this helps someone :-
public void genrateSignature() {
String salt = String.valueOf(Crypto.getRandomInteger());
String secretKey = 'secret_key';
String signature = generateHmacSHA256Signature(salt, secretKey);
System.debug('Signature : '+signature);
}
private static String generateHmacSHA256Signature(String saltValue, String secretKeyValue) {
String algorithmName = 'HmacSHA256';
Blob hmacData = Crypto.generateMac(algorithmName, Blob.valueOf(saltValue), Blob.valueOf(secretKeyValue));
return EncodingUtil.base64Encode(hmacData);
}
Thanks"

Interaction with Lotus Connections

I need to get the data from some lotus connection site, for example user's status, from the other site. I try to setup a connection with lotus via java, e.g.
> server = "https://" + path + param + "&format=full";
> URL profiles_url = new URL(server);
> // Open the URL: throws exception if not found
> HttpURLConnection profiles_conn = HttpURLConnection)profiles_url.openConnection();
> profiles_conn.connect();
> // Process the Atom feed in the response content
> readResponse(profiles_url.openStream(),args[0]);
But I always get the Response: HTTP/1.1 401 Unauthorized
Please give me any suggestions?
I solved the authentication issue this way:
protected void doView(RenderRequest rRequest, RenderResponse rResponse) throws PortletException, IOException, UnavailableException {
try {
rResponse.setContentType("text/html");
URL url = new URL(
"https://xxx/activities/service/atom2/todos");
URLConnection con = url.openConnection();
con.setConnectTimeout(150000);
con.setReadTimeout(150000);
writeCookies(con, rRequest);
DO_SOMETHING (con.getInputStream());
} catch (Exception ex) {
ex.printStackTrace();
}
}
private String doesLTPATokenCookieExists(RenderRequest request) {
Cookie[] cookie = request.getCookies();
for (int i = 0; i < cookie.length; i++) {
System.out.println("Cookie Name " + cookie[i].getName());
if (cookie[i].getName().equals("LtpaToken"))
return cookie[i].getValue();
}
return null;
}
public URLConnection writeCookies(URLConnection urlConn,
RenderRequest request) {
String cookieString = "";
cookieString += "LtpaToken" + "=" + doesLTPATokenCookieExists(request) + "; ";
urlConn.setRequestProperty("Cookie", cookieString);
return urlConn;
}
You don't mention how you're authenticating, which is crucial. As the 401 error implies, Connections isn't treating your request as being authenticated. You need a valid Authenticator instance in there, but your code snippet suggests you haven't got that going, correct?
(As an aside, the Apache Abdera project is recommended when working with the Lotus Connections API).