i'm using Geb Selenium with Phantomjs Driver, realy using a RemoteWebDriver for interact with a web page using the phantomjs running over a console, i'm using also Spring boot so i call my Groovy Geb scripts from a REST method, what i want is to, for example, running scripts that login two different users asynchronously and make some work in their accounts, but when i run my code is like the first loged user is used over the second, i check in my code if the user is loged then go to his account, is like Selenium or Phantomjs uses an only one Browser for all my request so when i do a request for login and then make another one the first login is presents, is there a way for run my request in an isolated browser or driver in my case, or maybe is because some kind of cookies?
this is the code where i do my login using Groovy geb (called from a REST method in Spring):
public void test_make_login(String login, String password){
def String imgUrl = null
Browser.drive {
to MyPage
makeLogin(login,password){
println page
imgUrl = profileThumbnail.attr("src")
}{
imgUrl = "none"
}
println imgUrl
}
}
I'm using Angular $resource for make my REST requests, in my program i want to get the profile loged picture of each user but all users haves the first loged accound picture.
Related
I am writing a chrome extension, using a content script to inject some javascript code. As follows:
let actualCode = 'My Injected JS Code';
let script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
For the injected script, I would like to use some value stored in chrome.storage.sync. However, I found that the API is unaccessible to the injected script (storage.sync is undefined). The API is only accessible within the content script, but not for the injected script. Any ideas how I could access chrome.storage API for the injected script too?
PS: I've registered the storage API in manifest.json
PS: When I open the developer's console on chrome and type "chrome.storage", it returns undefined too. I think this might be a permission problem?
The inject way you used for the script, made it work in the web page environment, which doesn't have access to most of Chrome Extensions API.
However, there is an option to use Messages API which allows sending requests from a webpage to the extension by ID.
In this case, you also need to implement a listener in your background page, to answer such requests.
P.S. chrome.storage API also shouldn't be available from page console. You may want to debug it from your background page console or select a content script environment (if the extension has such):
you can use window.postMessage({type : "MESSAGE_NAME"}) in injected script to send "message" event. then use windows.addEventListner("message", callback) in content_script to listen on "message" event.
You can specify the type of message to which you want to listen in the callback function. for instance
in content_script.js
function func_callback(){
if (event.data.type && event.data.type === "MESSAGE_NAME") {
# Your code
}`enter code here`
}
windows.addEventListner("message", func_callback)
in injected_script.js
<button onClick={()=>window.postMessage({type : "MESSAGE_NAME"})}></button>
I'm working on a CLI with OCLIF. In one of the commands, I need to simulate a couple of clicks on a web page (using the WebdriverIO framework for that). Before you're able to reach the desired page, there is a redirect to a page with a login prompt. When I use WebdriverIO methods related to alerts such as browser.getAlertText(), browser.sendAlertText() or browser.acceptAlert, I always get the error no such alert.
As an alternative, I tried to get the URL when I am on the page that shows the login prompt. With the URL, I wanted to do something like browser.url(https://<username>:<password>#<url>) to circumvent the prompt. However, browser.url() returns chrome-error://chromewebdata/ as URL when I'm on that page. I guess because the focus is on the prompt and that doesn't have an URL. I also don't know the URL before I land on that page. When being redirected, a query string parameter containing a token is added to the URL that I need.
A screenshot of the prompt:
Is it possible to handle this scenario with WebdriverIO? And if so, how?
You are on the right track, probably there are some fine-tunings that you need to address to get it working.
First off, regarding the chrome-error://chromewebdata errors, quoting Chrome DOCs:
If you see errors with a location like chrome-error://chromewebdata/
in the error stack, these errors are not from the extension or from
your app - they are usually a sign that Chrome was not able to load
your app.
When you see these errors, first check whether Chrome was able to load
your app. Does Chrome say "This site can't be reached" or something
similar? You must start your own server to run your app. Double-check
that your server is running, and that the url and port are configured
correctly.
A lot of words that sum up to: Chrome couldn't load the URL you used inside the browser.url() command.
I tried myself on The Internet - Basic Auth page. It worked like a charm.
URL without basic auth credentials:
URL WITH basic auth credentials:
Code used:
it('Bypass HTTP basic auth', () => {
browser.url('https://admin:admin#the-internet.herokuapp.com/basic_auth');
browser.waitForReadyState('complete');
const banner = $('div.example p').getText().trim();
expect(banner).to.equal('Congratulations! You must have the proper credentials.');
});
What I'd do is manually go through each step, trying to emulate the same flow in the script you're using. From history I can tell you, I dealt with some HTTP web-apps that required a refresh after issuing the basic auth browser.url() call.
Another way to tackle this is to make use of some custom browser profiles (Firefox | Chrome) . I know I wrote a tutorial on it somewhere on SO, but I'm too lazy to find it. I reference a similar post here.
Short story, manually complete the basic auth flow (logging in with credentials) in an incognito window (as to isolate the configurations). Open chrome://version/ in another tab of that session and store the contents of the Profile Path. That folder in going to keep all your sessions & preserve cookies and other browser data.
Lastly, in your currentCapabilities, update the browser-specific options to start the sessions with a custom profile, via the '--user-data-dir=/path/to/your/custom/profile. It should look something like this:
'goog:chromeOptions': {
args: [
'--user-data-dir=/Users/iamdanchiv/Desktop/scoped_dir18256_17319',
],
}
Good luck!
Our site uses ajax to navigate pages and that's making it hard to request a new session when the page changes. Ideally when a user changes pages, I'd like to stop the currently playing session and start a new session with the video that's on the new page.
On the first pageload, I append the https://www.gstatic.com/cv/js/sender/v1/cast_sender.js script, call the init method:
var sessionRequest = new chrome.cast.SessionRequest(applicationID);
var apiConfig = new chrome.cast.ApiConfig(sessionRequest,
this.sessionListener.bind(this),
this.receiverListener.bind(this));
chrome.cast.initialize(apiConfig, this.onInitSuccess.bind(this), this.onError.bind(this));
everything works fine, my callbacks are called and I can start the chromecast session.
On secondary page loads, I don't re-add the cast_sender.js script. When I call the initalize method and the sessionListener callback doesn't execute. If I try holding on to the session between pages, I can access the session and get to it's media object, but if I try calling any methods on the session or media object, I just get back an error:
TypeError: Cannot call method 'postMessage' of null
Seems like there's some magic binding that happens when executing the cast_sender.js script that I'm missing?
We've just released the Google Cast extension Beta that potentially addresses this issue. See my post: https://plus.google.com/+ShawnShen/posts/aVXSHyceNbR
You may add something like the following in your app to do both sync/async script loading.
window['_onGCastApiAvailable'] = (function(loaded, errorInfo) {
if (loaded) {
this.init();
} else {
this.appendMessage_(errorInfo);
}
}).bind(this);
I have a little question. I am working with NetSuite eCommerce and I need to check something, my site runs a script when user is logged, but sometimes it asks for a login even when still getting NetSuite Attributes. Something like this:
var loginEmail = "<%=getCurrentAttribute('customer','email')%>";
if(loginEmail==null || loginEmail=="") {
$("#cart").hide();
}
else {
$("#cart").show();
}
Do you know a specific NetSuite attribute or tag that I should be calling/using?
User sessions do time out after a period of inactivity, and user sessions are tracked with a cookie.
Try testing with a different browser - ie run NetSuite in FireFox and test the eCommerce functionality in Chrome or Safari, for instance.
Try nlapiGetLogin(). From NetSuite Help:
nlapiGetLogin
Returns the NetSuite login credentials of currently logged-in user.
This API is supported in user event, portlet, Suitelet, RESTlet, and SSP scripts. For information about the unit cost associated with this API, see API Governance.
Returns nlobjLogin
Since Version 2012.2
Example
This example shows how to get the credentials of the currently logged-in user.
//Get credentials of currently logged-in user
var login = nlapiGetLogin();
It doesn't say, but my thought is that this would return null if no user is logged in.
Use this code:
<%
var shoppingSession = nlapiGetWebContainer().getShoppingSession();
if (!shoppingSession.isLoggedIn())
$("#cart").hide();
else
$("#cart").show();
%>
In place of
<%=getCurrentAttribute('customer','email')%>
try using
<%=getCurrentAttribute('customer','entityid')%>
I'm using the Acegi plugin in my Grails app. After a user registers, he is redirected to an action that is protected. Therefore, he is shown the login form.
However, I would prefer if the user was automatically logged in as soon as he completes registration. It seems like I could achieve this by redirecting to the action that the login form uses
redirect(uri:"/j_acegi_security_check?j_username=${username}&j_password=${passed}")
But this would send a HTTP request to the client (and back to the server) which shows the user's password. Is there a way I can login automatically in a secure fashion?
Thanks,
Don
If you generate the controller classes for the spring security plugin (grails generate-registration) you'll see the following lines in RegisterController which does just what you want:
class RegisterController {
def daoAuthenticationProvider
...
def save = {
...
def auth = new AuthToken(person.username, params.passwd)
def authtoken = daoAuthenticationProvider.authenticate(auth)
SecurityContextHolder.context.authentication = authtoken
redirect uri: '/'
}
Be sure that params.passwd is the plain-text password (i.e. not hashed) and it works like a charm.
I haven't tried this with non-test code, but this is the method that I created to log a user in within my integration tests (after building/saving the appropriate users/roles in my test setup):
import org.codehaus.groovy.grails.plugins.springsecurity.GrailsDaoAuthenticationProvider
import org.springframework.security.providers.UsernamePasswordAuthenticationToken
import org.springframework.security.context.SecurityContextHolder
...
def logInAsUser(username, password) {
daoAuthenticationProvider.getUserCache().removeUserFromCache(username)
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password)
SecurityContextHolder.context.authentication = daoAuthenticationProvider.authenticate(token)
}
I construct and inject the authentication token in the security context. There might be a little more that you need to do to get your user logged in and past security, but this would be the start of whatever that is.
I'll actually need to do exactly what you're asking in a week or two for my current app, post back if you figure it out fully before I do :).
This is Burt Beckwith's answer (not mine)
(It was left as a comment by Burt, but I think it deserves to be more prominent)
If you don't have the password, you can load the user via
def user = User.findByUsername(username)
and setting the authority array in the 3-parameter constructor. Create the auths via
GrantedAuthority[] auths = user.authorities.collect { new GrantedAuthorityImpl(it.authority) }
Then you can omit the call to authenticate() and use:
SecurityContextHolder.context.authentication = new UsernamePasswordAuthenticationToken(username, 'unknown', auths)