Unable to click button using NHtmlUnit - oauth-2.0

I have a unit test which simulates a login on Uber. The goal is to acquire a token that isn't otherwise accessible without an interactive login. I've had this working in the passed but it appears the Uber login experience has changed and now I'm having issues getting NHtmlUnit to successfully submit the login button.
Here's my latest attempt: https://github.com/wadewegner/uber-sdk-for-net/blob/42fd845fe43e11e3153b07d830ed40e3577b1ed3/src/UberSDKForNet.FunctionalTests/Tests.cs#L100
Here's the key area:
var loginFormButtons = loginForm.GetElementsByTagName("button");
Assert.IsNotNull(loginFormButtons);
var loginButton = (HtmlButton)loginFormButtons.First();
Assert.IsNotNull(loginButton);
var loginButtonText = loginButton.AsText();
StringAssert.Contains("sign in", loginButtonText.toLowerCase());
loginButton.SetAttribute("type", "submit");
loginForm.AppendChild(loginButton);
var consentPage = (HtmlPage)loginButton.Click();
Assert.IsNotNull(consentPage);
I know the code is verbose, but unit testing NHtmlUnit is a nightmare. I've also tried a ton of different permutations, but they pretty much all end up with a HtmlButton.
Everything works great until https://github.com/wadewegner/uber-sdk-for-net/blob/42fd845fe43e11e3153b07d830ed40e3577b1ed3/src/UberSDKForNet.FunctionalTests/Tests.cs#L174. What I'd expect is for this to take me to the consent page where I'd either allow or deny the Uber app access to my information. However, it appears to simply reload the original page and consentPage appears to simply be the same as loginPage.
Any NHtmlUnit experts who might have some ideas?
The only thing I'll also point out is that in the past I was able to successfully use HtmlSubmitInput instead of HtmlButton but this appears to be one of the changes made by Uber. Perhaps this is part of the problem?

Well, it's not perfect, but it appears setting the WebClient to FIREFOX_17 instead of CHROME solved it.
var webClient = new WebClient(BrowserVersion.FIREFOX_17);
See here: https://github.com/wadewegner/uber-sdk-for-net/blob/ceb1cdf80cebb31608744c050b649ddd6a75fb7a/src/UberSDKForNet.FunctionalTests/Tests.cs#L107

Related

Playwright & Accessing sessionStorage

I have an application that I want to test with some automated UI tests, where the devs have stored some of the user's preferences in the sessionStorage. There appears to be a bug where the session storage isn't getting cleared out when we expect it to be. This is the bug I'm trying to recreate.
After fighting with pure Selenium for a while, I tried Playwright, and I almost have this working, but not quite.
I'm using C# (.NET 6) with Playwright.Nunit 1.27.1.
In my test, the user logs into the site, and after the site is logged into, I want to get the preferences object from the session storage. This is the code I'm using for that section:
// NOW GET SESSION
// sessionStorage.getItem('settingsObj')
var sessionStorage = await Page.EvaluateAsync<string>("() => JSON.stringify( sessionStorage.getItem('settingsObj'))");
Console.WriteLine($"STORAGE? {sessionStorage}");
}
When I run this test, the sessionStorage prints out as a NULL.
However, if I run this test in the debugger, with breakpoints on the var sessionStorage... line and the Console.WriteLine... lines, I see that the sessionStorage DOES contain my object during the run.
So. How do I get this object OUT so I can parse it?

UI5-Application: Call to functionimport works ONLY in WebIDE but fails everywhere else

We are developing a custom UI5 application.
It is developed in the WebIDE, and therefore deployed as a BSP.
When we use the underlying model for calls ( currently 3, no CRUD ), we chose the path of using ONLY functionimports to communicate with the backend.
All of them work with the POST method.
And all of them work ONLY inside the WebIDE.
Once, I access the BSP URL otherwise, we get HTTP 500 error with "error while requesting the ressource.
We already created links, to enable special portfowarding, no result.
Let's stick to my URL from the BSP first.
I paste it into my 3 browsers: 500.
We also created a special non dialogue-user with proper roles and permissions, and in the SICF tree we assigned it .
Again, when calling from inside the WebIDE, the functionimport-calls work, otherwise not.
Error-Logs are empty.
Dumps do not happen.
ST05 trace shows where 500 is passed, deeply inside the HTTP framework, yet no chance to spot the code location, neither a breaktpoint.
In SICF logon-settings we have:
Types all, also flagged "all", SAML: inherited from parent node, sec-sessions Not limited, fix user and pw, sec: Standard, auth:Standard Sap user.
The gui-options contain ONLY one flag: ~CHECK_CSRF_TOKEN 0.
In my client I use :
Where the model is initialized as :
function initModelV2() {
var sUrl = "/sap/opu/odata/sap/Z_this_is_a_company_secret_service/";
var oModel = new sap.ui.model.odata.v2.ODataModel(sUrl);
sap.ui.getCore().setModel(oModel);
}
What else can I do to get "at least closer" to the reason, WHY ?
I could solve it, and believe it or not, sometimes simple logic helps.
I debugged the backend of CL_HTTP_RESPONSE, and once I saw, GET_STATUS, I thought to look for SET_STATUS.
There it was:
this.rModel.setHeaders( {"X-Requested-With" : "X" } );
Was missing.
Though I set it in the manifest of my model, it was not passed.
Once set in the code, it worked.
I wonder, why it is not accepted in manifest.
I have an assumption.
1st: I have this in my manifest ( yellow arrow shows, where i HAD it set up before):
But I also have an instantiation in my code, in servicebindings.js with this code
Can it be, that, in the end, I have accidently created 2 models ?

In a Firefox extension, if I open a tab using a custom scheme, how do I close it, because my extension is not authorized for that scheme pattern?

I have a custom scheme mapped on my Windows machine: "dbn".
So, when I put dbn:/some/arguments in the Firefox address bar (or click on such a link), it launches in another application. This works great.
However, in a Firefox extension, I don't know how to "call" or "activate" this custom scheme except by opening a new tab, like this:
browser.tabs.create({ url: 'dbn:/some/arguments' });
That works fine, except now I have an open tab with dbn:/some/arguments as the URL. I have attempted to subsequently close it from my extension, but I can't because:
Error: Missing host permission for the tab
My extension doesn't have permissions for that "host."
I have tried to give it permissions via a match_patterns value of dbn:* but that throws an error when I try to reload the extension because those values apparently have to use one of the expected schemes (http, https, ftp, etc.).
I end up just having to close the tab manually, which isn't terrible, but is clearly sub-optimal.
So, two questions:
Is it possible to "call" a URL in such a way to activate a custom-mapped scheme on Windows without opening a tab? The only way I could think of doing this in such a way that it would activate my mapped command was to open a tab, but are there other ways?
If opening a new tab is the only way to do this, how do I close the tab I just opened without having the permissions problem I mention above?
Update
I don't think it's permissions anymore. The Promise simply won't resolve.
browser.tabs.create({ url: "some/url" })
.then(tab => console.error("I never get here"));
I've debugged up, down, and sideways. The new tab opens, and I can write to the log all around that operation, but the code in then just doesn't execute, no matter what I put in there. I tried to trap an error with try...catch, but that didn't trap anything.
I now think that permission above was coming from a different extension, not my extension. I don't think this has anything to do with the host.
AFA custom schemes, there is an open bug: Extend match patterns to handle custom protocol schemes
You can tabs.remove() a tab by its ID which you get from tabs.create().
async function fun() {
// note this is async
const tab = await browser.tabs.create({url: 'dbn:/some/arguments'});
// later remove it
browser.tabs.remove(tab.id);
}
// or
browser.tabs.create({url: 'dbn:/some/arguments'})
.then(tab => {
// do what is needed
// later remove it
browser.tabs.remove(tab.id);
});
Update:
Regarding the Promise, there is not enough information to pinpoint the issue.
Which permissions have been set?
Where is the code running?
Use catch to get more info about the Promise failure:
browser.tabs.create({url: "some/url"})
.then(tab => console.log(`Created new tab: ${tab.id}`))
.catch(error => console.log(error.message));

What would cause InternetExplorerMedium to work on one machine but not another?

I have a VBA script in Access that logs onto a website and downloads some data, I built it using a laptop and use the code of
Dim objIE As InternetExplorerMedium 'special object variable representing the IE browser
Dim aEle As HTMLLinkElement 'special object variable for an <a> (link) element
Dim element As HTMLLinkElement
Set objIE = New InternetExplorerMedium
On Error GoTo Errorhandler
objIE.Visible = False
DoCmd.Hourglass (True) 'navigate IE to this web page
objIE.navigate www.google.com ' google just for example
Then it inputs the login info into the proper boxes and logs in.
Which works fine, however I installed this front end on another user's PC and it no longer works, it just opens the page but fills in no info.
However, if I change,
Set objIE = New InternetExplorerMedium
to
Set objIE = CreateObject("InternetExplorer.Application")
then it works on their PC. But this change does not work on my laptop.
What would cause this issue and how could I standardize this so I can install on any windows machine without worry of this occurring.
Notes:
We are both on the company LAN, and both are running windows 10 Home.
It was something incredibly simple, I just had to add the website I was accessing as a trusted site in Internet Explorer.

Appium: dealing with android system interactions

I have a simple use-case. Within the android app, press a button and the browser app will open a URL.
The "Open With" dialog pop-up appears and allows you to select Browser or Chrome.
Which looks like this in the appium inspector:
<android.widget.ListView resource-id="android:id/resolver_list">
<android.widget.LinearLayout>
<android.widget.ImageView resource-id="android:id/icon">
<android.widget.LinearLayout>
<android.widget.TextView resource-id="android:id/text1">
<android.widget.LinearLayout>
<android.widget.ImageView resource-id="android:id/icon">
<android.widget.LinearLayout>
<android.widget.TextView resource-id="android:id/text1">
Attempting to automate this seems like it should be trivial, but is causing me trouble. I can get the text of both "Browser" and "Chrome" as discrete AndroidElements, but I cannot seem to be able to actually press the actual options.
Am I allowed to actually interact with these things or is this impossible because it's part of the android system itself?
To help figure this out, here is the setup of my page object.
#AndroidFindBy(id = "android:id/resolver_list")
private AndroidElement listParentElement;
public List<OpenWithOption> getOptions() {
/* ... */
List<MobileElement> elements = listParentElement
.findElementsById(SYS_ID_PREFIX + "text1"); // Here's where I can only get the text element itself but can't figure out how to get the elements above that.
return elements.stream()
.map(mobileElement -> new OpenWithOptionImpl(mobileElement.getText(), mobileElement))
.collect(toList());
}
This was a rookie mistake. Selecting the browser enabled the choice of "Just Once" or "Always" in the bottom of the screen and I didn't notice. I thought that just pressing the browser you wanted would launch it.

Resources